From ca8c8e79ded360e2d8aff6ade34aef1835825ba0 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 16 Mar 2025 14:01:04 -0400 Subject: [PATCH] Finish Java query tests; WIP on DocEx declarations --- src/jvm/src/main/kotlin/Configuration.kt | 7 +- src/jvm/src/main/kotlin/Dialect.kt | 7 +- src/jvm/src/main/kotlin/DocumentException.kt | 2 +- src/jvm/src/main/kotlin/Field.kt | 1 - src/jvm/src/main/kotlin/FieldFormat.kt | 1 + src/jvm/src/main/kotlin/FieldMatch.kt | 1 + src/jvm/src/main/kotlin/Op.kt | 10 + src/jvm/src/main/kotlin/Parameter.kt | 5 +- .../src/main/kotlin/extensions/Connection.kt | 15 +- src/jvm/src/main/kotlin/jvm/Count.kt | 17 +- src/jvm/src/main/kotlin/jvm/Custom.kt | 19 ++ src/jvm/src/main/kotlin/jvm/Definition.kt | 11 +- .../integration/common/CountFunctions.java | 6 +- .../jvm/integration/postgresql/CountIT.java | 6 +- .../java/jvm/integration/sqlite/CountIT.java | 6 +- .../documents/java/query/WhereTest.java | 172 ++++++++++++++++++ src/jvm/src/test/kotlin/FieldTest.kt | 87 ++++----- src/jvm/src/test/kotlin/query/WhereTest.kt | 75 ++++---- 18 files changed, 348 insertions(+), 100 deletions(-) create mode 100644 src/jvm/src/test/java/solutions/bitbadger/documents/java/query/WhereTest.java diff --git a/src/jvm/src/main/kotlin/Configuration.kt b/src/jvm/src/main/kotlin/Configuration.kt index e89793a..d40f653 100644 --- a/src/jvm/src/main/kotlin/Configuration.kt +++ b/src/jvm/src/main/kotlin/Configuration.kt @@ -21,7 +21,7 @@ object Configuration { var idStringLength = 16 /** The derived dialect value from the connection string */ - internal var dialectValue: Dialect? = null + private var dialectValue: Dialect? = null /** The connection string for the JDBC connection */ @JvmStatic @@ -35,12 +35,13 @@ object Configuration { * Retrieve a new connection to the configured database * * @return A new connection to the configured database - * @throws IllegalArgumentException If the connection string is not set before calling this + * @throws DocumentException If the connection string is not set before calling this */ + @Throws(DocumentException::class) @JvmStatic fun dbConn(): Connection { if (connectionString == null) { - throw IllegalArgumentException("Please provide a connection string before attempting data access") + throw DocumentException("Please provide a connection string before attempting data access") } return DriverManager.getConnection(connectionString) } diff --git a/src/jvm/src/main/kotlin/Dialect.kt b/src/jvm/src/main/kotlin/Dialect.kt index 986dddb..1d0c32b 100644 --- a/src/jvm/src/main/kotlin/Dialect.kt +++ b/src/jvm/src/main/kotlin/Dialect.kt @@ -1,11 +1,14 @@ package solutions.bitbadger.documents +import kotlin.jvm.Throws + /** * The SQL dialect to use when building queries */ enum class Dialect { /** PostgreSQL */ POSTGRESQL, + /** SQLite */ SQLITE; @@ -18,9 +21,11 @@ enum class Dialect { * @return The dialect for the connection string * @throws DocumentException If the dialect cannot be determined */ + @Throws(DocumentException::class) + @JvmStatic fun deriveFromConnectionString(connectionString: String): Dialect = when { - connectionString.contains(":sqlite:") -> SQLITE + connectionString.contains(":sqlite:") -> SQLITE connectionString.contains(":postgresql:") -> POSTGRESQL else -> throw DocumentException("Cannot determine dialect from [$connectionString]") } diff --git a/src/jvm/src/main/kotlin/DocumentException.kt b/src/jvm/src/main/kotlin/DocumentException.kt index 4a292e6..d415801 100644 --- a/src/jvm/src/main/kotlin/DocumentException.kt +++ b/src/jvm/src/main/kotlin/DocumentException.kt @@ -6,4 +6,4 @@ package solutions.bitbadger.documents * @param message The message for the exception * @param cause The underlying exception (optional) */ -class DocumentException(message: String, cause: Throwable? = null) : Exception(message, cause) \ No newline at end of file +class DocumentException @JvmOverloads constructor(message: String, cause: Throwable? = null) : Exception(message, cause) diff --git a/src/jvm/src/main/kotlin/Field.kt b/src/jvm/src/main/kotlin/Field.kt index 9a4c899..c4d017a 100644 --- a/src/jvm/src/main/kotlin/Field.kt +++ b/src/jvm/src/main/kotlin/Field.kt @@ -118,7 +118,6 @@ class Field private constructor( is ComparisonInArray<*> -> { val mkString = Configuration.dialect("append parameters for InArray") == Dialect.POSTGRESQL - // TODO: I think this is actually Pair> comparison.value.second.forEachIndexed { index, item -> if (mkString) { existing.add(Parameter("${parameterName}_$index", ParameterType.STRING, "$item")) diff --git a/src/jvm/src/main/kotlin/FieldFormat.kt b/src/jvm/src/main/kotlin/FieldFormat.kt index c804a87..d323696 100644 --- a/src/jvm/src/main/kotlin/FieldFormat.kt +++ b/src/jvm/src/main/kotlin/FieldFormat.kt @@ -6,6 +6,7 @@ package solutions.bitbadger.documents enum class FieldFormat { /** Retrieve the field as a SQL value (string in PostgreSQL, best guess in SQLite */ SQL, + /** Retrieve the field as a JSON value */ JSON } diff --git a/src/jvm/src/main/kotlin/FieldMatch.kt b/src/jvm/src/main/kotlin/FieldMatch.kt index 3b1d3ff..3af7230 100644 --- a/src/jvm/src/main/kotlin/FieldMatch.kt +++ b/src/jvm/src/main/kotlin/FieldMatch.kt @@ -6,6 +6,7 @@ package solutions.bitbadger.documents enum class FieldMatch(val sql: String) { /** Match any of the field criteria (`OR`) */ ANY("OR"), + /** Match all the field criteria (`AND`) */ ALL("AND"), } diff --git a/src/jvm/src/main/kotlin/Op.kt b/src/jvm/src/main/kotlin/Op.kt index 61723c9..45004f4 100644 --- a/src/jvm/src/main/kotlin/Op.kt +++ b/src/jvm/src/main/kotlin/Op.kt @@ -6,24 +6,34 @@ package solutions.bitbadger.documents enum class Op(val sql: String) { /** Compare using equality */ EQUAL("="), + /** Compare using greater-than */ GREATER(">"), + /** Compare using greater-than-or-equal-to */ GREATER_OR_EQUAL(">="), + /** Compare using less-than */ LESS("<"), + /** Compare using less-than-or-equal-to */ LESS_OR_EQUAL("<="), + /** Compare using inequality */ NOT_EQUAL("<>"), + /** Compare between two values */ BETWEEN("BETWEEN"), + /** Compare existence in a list of values */ IN("IN"), + /** Compare overlap between an array and a list of values */ IN_ARRAY("??|"), + /** Compare existence */ EXISTS("IS NOT NULL"), + /** Compare nonexistence */ NOT_EXISTS("IS NULL") } diff --git a/src/jvm/src/main/kotlin/Parameter.kt b/src/jvm/src/main/kotlin/Parameter.kt index 1bd707b..3e9c9a7 100644 --- a/src/jvm/src/main/kotlin/Parameter.kt +++ b/src/jvm/src/main/kotlin/Parameter.kt @@ -2,6 +2,7 @@ package solutions.bitbadger.documents import java.sql.PreparedStatement import java.sql.Types +import kotlin.jvm.Throws /** * A parameter to use for a query @@ -22,7 +23,9 @@ class Parameter(val name: String, val type: ParameterType, val value: T) { * * @param stmt The prepared statement to which this parameter should be bound * @param index The index (1-based) to which the parameter should be bound + * @throws DocumentException If a number parameter is given a non-numeric value */ + @Throws(DocumentException::class) fun bind(stmt: PreparedStatement, index: Int) { when (type) { ParameterType.NUMBER -> { @@ -33,7 +36,7 @@ class Parameter(val name: String, val type: ParameterType, val value: T) { is Int -> stmt.setInt(index, value) is Long -> stmt.setLong(index, value) else -> throw DocumentException( - "Number parameter must be Byte, Short, Int, or Long (${value!!::class.simpleName})" + "Number parameter must be Byte, Short, Int, or Long (${value::class.simpleName})" ) } } diff --git a/src/jvm/src/main/kotlin/extensions/Connection.kt b/src/jvm/src/main/kotlin/extensions/Connection.kt index 8c4267a..bdc56ff 100644 --- a/src/jvm/src/main/kotlin/extensions/Connection.kt +++ b/src/jvm/src/main/kotlin/extensions/Connection.kt @@ -6,6 +6,7 @@ import solutions.bitbadger.documents.* import solutions.bitbadger.documents.jvm.* import java.sql.Connection import java.sql.ResultSet +import kotlin.jvm.Throws // ~~~ CUSTOM QUERIES ~~~ @@ -17,7 +18,9 @@ import java.sql.ResultSet * @param clazz The class of the document to be returned * @param mapFunc The mapping function between the document and the domain item * @return A list of results for the given query + * @throws DocumentException If parameters are invalid */ +@Throws(DocumentException::class) fun Connection.customList( query: String, parameters: Collection> = listOf(), @@ -34,7 +37,9 @@ fun Connection.customList( * @param clazz The class of the document to be returned * @param mapFunc The mapping function between the document and the domain item * @return The document if one matches the query, `null` otherwise + * @throws DocumentException If parameters are invalid */ +@Throws(DocumentException::class) fun Connection.customSingle( query: String, parameters: Collection> = listOf(), @@ -48,7 +53,9 @@ fun Connection.customSingle( * * @param query The query to retrieve the results * @param parameters Parameters to use for the query + * @throws DocumentException If parameters are invalid */ +@Throws(DocumentException::class) fun Connection.customNonQuery(query: String, parameters: Collection> = listOf()) = Custom.nonQuery(query, parameters, this) @@ -60,7 +67,9 @@ fun Connection.customNonQuery(query: String, parameters: Collection * @param clazz The class of the document to be returned * @param mapFunc The mapping function between the document and the domain item * @return The scalar value from the query + * @throws DocumentException If parameters are invalid */ +@Throws(DocumentException::class) fun Connection.customScalar( query: String, parameters: Collection> = listOf(), @@ -109,7 +118,7 @@ fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex) * @param document The document to be inserted */ fun Connection.insert(tableName: String, document: TDoc) = - Document.insert(tableName, document, this) + Document.insert(tableName, document, this) /** * Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert") @@ -137,7 +146,9 @@ fun Connection.update(tableName: String, docId: TKey, document: TDo * * @param tableName The name of the table in which documents should be counted * @return A count of the documents in the table + * @throws DocumentException If any dependent process does */ +@Throws(DocumentException::class) fun Connection.countAll(tableName: String) = Count.all(tableName, this) @@ -148,7 +159,9 @@ fun Connection.countAll(tableName: String) = * @param fields The fields which should be compared * @param howMatched How the fields should be matched * @return A count of the matching documents in the table + * @throws DocumentException If the dialect has not been configured */ +@Throws(DocumentException::class) @JvmOverloads fun Connection.countByFields(tableName: String, fields: Collection>, howMatched: FieldMatch? = null) = Count.byFields(tableName, fields, howMatched, this) diff --git a/src/jvm/src/main/kotlin/jvm/Count.kt b/src/jvm/src/main/kotlin/jvm/Count.kt index 1127d80..25f87e3 100644 --- a/src/jvm/src/main/kotlin/jvm/Count.kt +++ b/src/jvm/src/main/kotlin/jvm/Count.kt @@ -4,6 +4,7 @@ import solutions.bitbadger.documents.* import solutions.bitbadger.documents.query.CountQuery import solutions.bitbadger.documents.extensions.customScalar import java.sql.Connection +import kotlin.jvm.Throws /** * Functions to count documents @@ -16,7 +17,9 @@ object Count { * @param tableName The name of the table in which documents should be counted * @param conn The connection over which documents should be counted * @return A count of the documents in the table + * @throws DocumentException If any dependent process does */ + @Throws(DocumentException::class) @JvmStatic fun all(tableName: String, conn: Connection) = conn.customScalar(CountQuery.all(tableName), listOf(), Long::class.java, Results::toCount) @@ -26,7 +29,9 @@ object Count { * * @param tableName The name of the table in which documents should be counted * @return A count of the documents in the table + * @throws DocumentException If no connection string has been set */ + @Throws(DocumentException::class) @JvmStatic fun all(tableName: String) = Configuration.dbConn().use { all(tableName, it) } @@ -39,7 +44,9 @@ object Count { * @param howMatched How the fields should be matched * @param conn The connection on which the deletion should be executed * @return A count of the matching documents in the table + * @throws DocumentException If no dialect has been configured */ + @Throws(DocumentException::class) @JvmStatic @JvmOverloads fun byFields( @@ -64,7 +71,9 @@ object Count { * @param fields The fields which should be compared * @param howMatched How the fields should be matched * @return A count of the matching documents in the table + * @throws DocumentException If no connection string has been set */ + @Throws(DocumentException::class) @JvmStatic @JvmOverloads fun byFields(tableName: String, fields: Collection>, howMatched: FieldMatch? = null) = @@ -79,6 +88,7 @@ object Count { * @return A count of the matching documents in the table * @throws DocumentException If called on a SQLite connection */ + @Throws(DocumentException::class) @JvmStatic fun byContains(tableName: String, criteria: TContains, conn: Connection) = conn.customScalar( @@ -94,8 +104,9 @@ object Count { * @param tableName The name of the table in which documents should be counted * @param criteria The object for which JSON containment should be checked * @return A count of the matching documents in the table - * @throws DocumentException If called on a SQLite connection + * @throws DocumentException If no connection string has been set, or if called on a SQLite connection */ + @Throws(DocumentException::class) @JvmStatic fun byContains(tableName: String, criteria: TContains) = Configuration.dbConn().use { byContains(tableName, criteria, it) } @@ -109,6 +120,7 @@ object Count { * @return A count of the matching documents in the table * @throws DocumentException If called on a SQLite connection */ + @Throws(DocumentException::class) @JvmStatic fun byJsonPath(tableName: String, path: String, conn: Connection) = conn.customScalar( @@ -124,8 +136,9 @@ object Count { * @param tableName The name of the table in which documents should be counted * @param path The JSON path comparison to match * @return A count of the matching documents in the table - * @throws DocumentException If called on a SQLite connection + * @throws DocumentException If no connection string has been set, or if called on a SQLite connection */ + @Throws(DocumentException::class) @JvmStatic fun byJsonPath(tableName: String, path: String) = Configuration.dbConn().use { byJsonPath(tableName, path, it) } diff --git a/src/jvm/src/main/kotlin/jvm/Custom.kt b/src/jvm/src/main/kotlin/jvm/Custom.kt index b4f5d54..d438b64 100644 --- a/src/jvm/src/main/kotlin/jvm/Custom.kt +++ b/src/jvm/src/main/kotlin/jvm/Custom.kt @@ -1,9 +1,11 @@ package solutions.bitbadger.documents.jvm import solutions.bitbadger.documents.Configuration +import solutions.bitbadger.documents.DocumentException import solutions.bitbadger.documents.Parameter import java.sql.Connection import java.sql.ResultSet +import kotlin.jvm.Throws object Custom { @@ -16,7 +18,9 @@ object Custom { * @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 + * @throws DocumentException If parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun list( query: String, @@ -34,7 +38,9 @@ object Custom { * @param clazz The class of the document to be returned * @param mapFunc The mapping function between the document and the domain item * @return A list of results for the given query + * @throws DocumentException If no connection string has been set, or if parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun list( query: String, @@ -52,7 +58,9 @@ object Custom { * @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 + * @throws DocumentException If parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun single( query: String, @@ -70,7 +78,9 @@ object Custom { * @param clazz The class of the document to be returned * @param mapFunc The mapping function between the document and the domain item * @return The document if one matches the query, `null` otherwise + * @throws DocumentException If no connection string has been set, or if parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun single( query: String, @@ -85,7 +95,9 @@ object Custom { * @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 + * @throws DocumentException If parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun nonQuery(query: String, parameters: Collection> = listOf(), conn: Connection) { Parameters.apply(conn, query, parameters).use { it.executeUpdate() } @@ -96,7 +108,9 @@ object Custom { * * @param query The query to retrieve the results * @param parameters Parameters to use for the query + * @throws DocumentException If no connection string has been set, or if parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic @JvmOverloads fun nonQuery(query: String, parameters: Collection> = listOf()) = @@ -110,7 +124,9 @@ object Custom { * @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 + * @throws DocumentException If parameters are invalid */ + @Throws(DocumentException::class) @JvmStatic fun scalar( query: String, @@ -132,7 +148,10 @@ object Custom { * @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 + * @throws DocumentException If no connection string has been set, or if parameters are invalid */ + @Throws(DocumentException::class) + @JvmStatic fun scalar( query: String, parameters: Collection> = listOf(), diff --git a/src/jvm/src/main/kotlin/jvm/Definition.kt b/src/jvm/src/main/kotlin/jvm/Definition.kt index 8e18818..585e7d9 100644 --- a/src/jvm/src/main/kotlin/jvm/Definition.kt +++ b/src/jvm/src/main/kotlin/jvm/Definition.kt @@ -6,6 +6,7 @@ import solutions.bitbadger.documents.DocumentIndex import solutions.bitbadger.documents.extensions.customNonQuery import solutions.bitbadger.documents.query.DefinitionQuery import java.sql.Connection +import kotlin.jvm.Throws /** * Functions to define tables and indexes @@ -17,7 +18,9 @@ object Definition { * * @param tableName The table whose existence should be ensured (may include schema) * @param conn The connection on which the query should be executed + * @throws DocumentException If the dialect is not configured */ + @Throws(DocumentException::class) @JvmStatic fun ensureTable(tableName: String, conn: Connection) = Configuration.dialect("ensure $tableName exists").let { @@ -29,7 +32,9 @@ object Definition { * Create a document table if necessary * * @param tableName The table whose existence should be ensured (may include schema) + * @throws DocumentException If no connection string has been set */ + @Throws(DocumentException::class) @JvmStatic fun ensureTable(tableName: String) = Configuration.dbConn().use { ensureTable(tableName, it) } @@ -41,7 +46,9 @@ object Definition { * @param indexName The name of the index to create * @param fields One or more fields to be indexed * @param conn The connection on which the query should be executed + * @throws DocumentException If any dependent process does */ + @Throws(DocumentException::class) @JvmStatic fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection, conn: Connection) = conn.customNonQuery(DefinitionQuery.ensureIndexOn(tableName, indexName, fields)) @@ -52,7 +59,9 @@ object Definition { * @param tableName The table to be indexed (may include schema) * @param indexName The name of the index to create * @param fields One or more fields to be indexed + * @throws DocumentException If no connection string has been set, or if any dependent process does */ + @Throws(DocumentException::class) @JvmStatic fun ensureFieldIndex(tableName: String, indexName: String, fields: Collection) = Configuration.dbConn().use { ensureFieldIndex(tableName, indexName, fields, it) } @@ -75,7 +84,7 @@ object Definition { * * @param tableName The table to be indexed (may include schema) * @param indexType The type of index to ensure - * @throws DocumentException If called on a SQLite connection + * @throws DocumentException If no connection string has been set, or if called on a SQLite connection */ @Throws(DocumentException::class) @JvmStatic diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CountFunctions.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CountFunctions.java index c32598d..a502241 100644 --- a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CountFunctions.java +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/common/CountFunctions.java @@ -17,18 +17,18 @@ import static solutions.bitbadger.documents.support.TypesKt.TEST_TABLE; */ final public class CountFunctions { - public static void all(ThrowawayDatabase db) { + public static void all(ThrowawayDatabase db) throws DocumentException { JsonDocument.load(db); assertEquals(5L, countAll(db.getConn(), TEST_TABLE), "There should have been 5 documents in the table"); } - public static void byFieldsNumeric(ThrowawayDatabase db) { + public static void byFieldsNumeric(ThrowawayDatabase db) throws DocumentException { JsonDocument.load(db); assertEquals(3L, countByFields(db.getConn(), TEST_TABLE, List.of(Field.between("numValue", 10, 20))), "There should have been 3 matching documents"); } - public static void byFieldsAlpha(ThrowawayDatabase db) { + public static void byFieldsAlpha(ThrowawayDatabase db) throws DocumentException { JsonDocument.load(db); assertEquals(1L, countByFields(db.getConn(), TEST_TABLE, List.of(Field.between("value", "aardvark", "apple"))), "There should have been 1 matching document"); diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CountIT.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CountIT.java index 97c1d3f..def860b 100644 --- a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CountIT.java +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/postgresql/CountIT.java @@ -14,7 +14,7 @@ public class CountIT { @Test @DisplayName("all counts all documents") - public void all() { + public void all() throws DocumentException { try (PgDB db = new PgDB()) { CountFunctions.all(db); } @@ -22,7 +22,7 @@ public class CountIT { @Test @DisplayName("byFields counts documents by a numeric value") - public void byFieldsNumeric() { + public void byFieldsNumeric() throws DocumentException { try (PgDB db = new PgDB()) { CountFunctions.byFieldsNumeric(db); } @@ -30,7 +30,7 @@ public class CountIT { @Test @DisplayName("byFields counts documents by a alphanumeric value") - public void byFieldsAlpha() { + public void byFieldsAlpha() throws DocumentException { try (PgDB db = new PgDB()) { CountFunctions.byFieldsAlpha(db); } diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CountIT.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CountIT.java index 38fda0b..1d9078b 100644 --- a/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CountIT.java +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/jvm/integration/sqlite/CountIT.java @@ -16,7 +16,7 @@ public class CountIT { @Test @DisplayName("all counts all documents") - public void all() { + public void all() throws DocumentException { try (SQLiteDB db = new SQLiteDB()) { CountFunctions.all(db); } @@ -24,7 +24,7 @@ public class CountIT { @Test @DisplayName("byFields counts documents by a numeric value") - public void byFieldsNumeric() { + public void byFieldsNumeric() throws DocumentException { try (SQLiteDB db = new SQLiteDB()) { CountFunctions.byFieldsNumeric(db); } @@ -32,7 +32,7 @@ public class CountIT { @Test @DisplayName("byFields counts documents by a alphanumeric value") - public void byFieldsAlpha() { + public void byFieldsAlpha() throws DocumentException { try (SQLiteDB db = new SQLiteDB()) { CountFunctions.byFieldsAlpha(db); } diff --git a/src/jvm/src/test/java/solutions/bitbadger/documents/java/query/WhereTest.java b/src/jvm/src/test/java/solutions/bitbadger/documents/java/query/WhereTest.java new file mode 100644 index 0000000..13de7d9 --- /dev/null +++ b/src/jvm/src/test/java/solutions/bitbadger/documents/java/query/WhereTest.java @@ -0,0 +1,172 @@ +package solutions.bitbadger.documents.java.query; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import solutions.bitbadger.documents.DocumentException; +import solutions.bitbadger.documents.Field; +import solutions.bitbadger.documents.FieldMatch; +import solutions.bitbadger.documents.query.Where; +import solutions.bitbadger.documents.support.ForceDialect; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Unit tests for the `Where` object + */ +@DisplayName("JVM | Java | Query | Where") +final public class WhereTest { + + /** + * Clear the connection string (resets Dialect) + */ + @AfterEach + public void cleanUp() { + ForceDialect.none(); + } + + @Test + @DisplayName("byFields is blank when given no fields") + public void byFieldsBlankIfEmpty() throws DocumentException { + assertEquals("", Where.byFields(List.of())); + } + + @Test + @DisplayName("byFields generates one numeric field | PostgreSQL") + public void byFieldsOneFieldPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("(data->>'it')::numeric = :that", Where.byFields(List.of(Field.equal("it", 9, ":that")))); + } + + @Test + @DisplayName("byFields generates one alphanumeric field | PostgreSQL") + public void byFieldsOneAlphaFieldPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data->>'it' = :that", Where.byFields(List.of(Field.equal("it", "", ":that")))); + } + + @Test + @DisplayName("byFields generates one field | SQLite") + public void byFieldsOneFieldSQLite() throws DocumentException { + ForceDialect.sqlite(); + assertEquals("data->>'it' = :that", Where.byFields(List.of(Field.equal("it", "", ":that")))); + } + + @Test + @DisplayName("byFields generates multiple fields w/ default match | PostgreSQL") + public void byFieldsMultipleDefaultPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data->>'1' = :one AND (data->>'2')::numeric = :two AND data->>'3' = :three", + Where.byFields(List.of( + Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")))); + } + + @Test + @DisplayName("byFields generates multiple fields w/ default match | SQLite") + public void byFieldsMultipleDefaultSQLite() throws DocumentException { + ForceDialect.sqlite(); + assertEquals("data->>'1' = :one AND data->>'2' = :two AND data->>'3' = :three", + Where.byFields(List.of( + Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")))); + } + + @Test + @DisplayName("byFields generates multiple fields w/ ANY match | PostgreSQL") + public void byFieldsMultipleAnyPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data->>'1' = :one OR (data->>'2')::numeric = :two OR data->>'3' = :three", + Where.byFields(List.of( + Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")), + FieldMatch.ANY)); + } + + @Test + @DisplayName("byFields generates multiple fields w/ ANY match | SQLite") + public void byFieldsMultipleAnySQLite() throws DocumentException { + ForceDialect.sqlite(); + assertEquals("data->>'1' = :one OR data->>'2' = :two OR data->>'3' = :three", + Where.byFields(List.of( + Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")), + FieldMatch.ANY)); + } + + @Test + @DisplayName("byId generates defaults for alphanumeric key | PostgreSQL") + public void byIdDefaultAlphaPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data->>'id' = :id", Where.byId(":id", "")); + } + + @Test + @DisplayName("byId generates defaults for numeric key | PostgreSQL") + public void byIdDefaultNumericPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("(data->>'id')::numeric = :id", Where.byId(":id", 5)); + } + + @Test + @DisplayName("byId generates defaults | SQLite") + public void byIdDefaultSQLite() throws DocumentException { + ForceDialect.sqlite(); + assertEquals("data->>'id' = :id", Where.byId(":id", "")); + } + + @Test + @DisplayName("byId generates named ID | PostgreSQL") + public void byIdDefaultNamedPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data->>'id' = :key", Where.byId(":key")); + } + + @Test + @DisplayName("byId generates named ID | SQLite") + public void byIdDefaultNamedSQLite() throws DocumentException { + ForceDialect.sqlite(); + assertEquals("data->>'id' = :key", Where.byId(":key")); + } + + @Test + @DisplayName("jsonContains generates defaults | PostgreSQL") + public void jsonContainsDefaultPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data @> :criteria", Where.jsonContains()); + } + + @Test + @DisplayName("jsonContains generates named parameter | PostgreSQL") + public void jsonContainsNamedPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("data @> :it", Where.jsonContains(":it")); + } + + @Test + @DisplayName("jsonContains fails | SQLite") + public void jsonContainsFailsSQLite() { + ForceDialect.sqlite(); + assertThrows(DocumentException.class, Where::jsonContains); + } + + @Test + @DisplayName("jsonPathMatches generates defaults | PostgreSQL") + public void jsonPathMatchDefaultPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("jsonb_path_exists(data, :path::jsonpath)", Where.jsonPathMatches()); + } + + @Test + @DisplayName("jsonPathMatches generates named parameter | PostgreSQL") + public void jsonPathMatchNamedPostgres() throws DocumentException { + ForceDialect.postgres(); + assertEquals("jsonb_path_exists(data, :jp::jsonpath)", Where.jsonPathMatches(":jp")); + } + + @Test + @DisplayName("jsonPathMatches fails | SQLite") + public void jsonPathFailsSQLite() { + ForceDialect.sqlite(); + assertThrows(DocumentException.class, Where::jsonPathMatches); + } +} diff --git a/src/jvm/src/test/kotlin/FieldTest.kt b/src/jvm/src/test/kotlin/FieldTest.kt index 12b71e5..4544d20 100644 --- a/src/jvm/src/test/kotlin/FieldTest.kt +++ b/src/jvm/src/test/kotlin/FieldTest.kt @@ -4,6 +4,7 @@ import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows +import solutions.bitbadger.documents.support.ForceDialect import kotlin.test.assertEquals import kotlin.test.assertNotSame import kotlin.test.assertNull @@ -19,7 +20,7 @@ class FieldTest { */ @AfterEach fun cleanUp() { - Configuration.dialectValue = null + ForceDialect.none() } // ~~~ INSTANCE METHODS ~~~ @@ -120,178 +121,178 @@ class FieldTest { "Path not correct") @Test - @DisplayName("toWhere generates for exists w/o qualifier (PostgreSQL)") + @DisplayName("toWhere generates for exists w/o qualifier | PostgreSQL") fun toWhereExistsNoQualPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'that_field' IS NOT NULL", Field.exists("that_field").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for exists w/o qualifier (SQLite)") + @DisplayName("toWhere generates for exists w/o qualifier | SQLite") fun toWhereExistsNoQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'that_field' IS NOT NULL", Field.exists("that_field").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for not-exists w/o qualifier (PostgreSQL)") + @DisplayName("toWhere generates for not-exists w/o qualifier | PostgreSQL") fun toWhereNotExistsNoQualPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'a_field' IS NULL", Field.notExists("a_field").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for not-exists w/o qualifier (SQLite)") + @DisplayName("toWhere generates for not-exists w/o qualifier | SQLite") fun toWhereNotExistsNoQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'a_field' IS NULL", Field.notExists("a_field").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/o qualifier, numeric range (PostgreSQL)") + @DisplayName("toWhere generates for BETWEEN w/o qualifier, numeric range | PostgreSQL") fun toWhereBetweenNoQualNumericPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(data->>'age')::numeric BETWEEN @agemin AND @agemax", Field.between("age", 13, 17, "@age").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/o qualifier, alphanumeric range (PostgreSQL)") + @DisplayName("toWhere generates for BETWEEN w/o qualifier, alphanumeric range | PostgreSQL") fun toWhereBetweenNoQualAlphaPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'city' BETWEEN :citymin AND :citymax", Field.between("city", "Atlanta", "Chicago", ":city").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/o qualifier (SQLite)") + @DisplayName("toWhere generates for BETWEEN w/o qualifier | SQLite") fun toWhereBetweenNoQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'age' BETWEEN @agemin AND @agemax", Field.between("age", 13, 17, "@age").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/ qualifier, numeric range (PostgreSQL)") + @DisplayName("toWhere generates for BETWEEN w/ qualifier, numeric range | PostgreSQL") fun toWhereBetweenQualNumericPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(test.data->>'age')::numeric BETWEEN @agemin AND @agemax", Field.between("age", 13, 17, "@age").withQualifier("test").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/ qualifier, alphanumeric range (PostgreSQL)") + @DisplayName("toWhere generates for BETWEEN w/ qualifier, alphanumeric range | PostgreSQL") fun toWhereBetweenQualAlphaPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("unit.data->>'city' BETWEEN :citymin AND :citymax", Field.between("city", "Atlanta", "Chicago", ":city").withQualifier("unit").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for BETWEEN w/ qualifier (SQLite)") + @DisplayName("toWhere generates for BETWEEN w/ qualifier | SQLite") fun toWhereBetweenQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("my.data->>'age' BETWEEN @agemin AND @agemax", Field.between("age", 13, 17, "@age").withQualifier("my").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for IN/any, numeric values (PostgreSQL)") + @DisplayName("toWhere generates for IN/any, numeric values | PostgreSQL") fun toWhereAnyNumericPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)", Field.any("even", listOf(2, 4, 6), ":nbr").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for IN/any, alphanumeric values (PostgreSQL)") + @DisplayName("toWhere generates for IN/any, alphanumeric values | PostgreSQL") fun toWhereAnyAlphaPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'test' IN (:city_0, :city_1)", Field.any("test", listOf("Atlanta", "Chicago"), ":city").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for IN/any (SQLite)") + @DisplayName("toWhere generates for IN/any | SQLite") fun toWhereAnySQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'test' IN (:city_0, :city_1)", Field.any("test", listOf("Atlanta", "Chicago"), ":city").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for inArray (PostgreSQL)") + @DisplayName("toWhere generates for inArray | PostgreSQL") fun toWhereInArrayPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]", Field.inArray("even", "tbl", listOf(2, 4, 6, 8), ":it").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for inArray (SQLite)") + @DisplayName("toWhere generates for inArray | SQLite") fun toWhereInArraySQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("EXISTS (SELECT 1 FROM json_each(tbl.data, '$.test') WHERE value IN (:city_0, :city_1))", Field.inArray("test", "tbl", listOf("Atlanta", "Chicago"), ":city").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for others w/o qualifier (PostgreSQL)") + @DisplayName("toWhere generates for others w/o qualifier | PostgreSQL") fun toWhereOtherNoQualPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'some_field' = :value", Field.equal("some_field", "", ":value").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates for others w/o qualifier (SQLite)") + @DisplayName("toWhere generates for others w/o qualifier | SQLite") fun toWhereOtherNoQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'some_field' = :value", Field.equal("some_field", "", ":value").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates no-parameter w/ qualifier (PostgreSQL)") + @DisplayName("toWhere generates no-parameter w/ qualifier | PostgreSQL") fun toWhereNoParamWithQualPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists("no_field").withQualifier("test").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates no-parameter w/ qualifier (SQLite)") + @DisplayName("toWhere generates no-parameter w/ qualifier | SQLite") fun toWhereNoParamWithQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("test.data->>'no_field' IS NOT NULL", Field.exists("no_field").withQualifier("test").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates parameter w/ qualifier (PostgreSQL)") + @DisplayName("toWhere generates parameter w/ qualifier | PostgreSQL") fun toWhereParamWithQualPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(q.data->>'le_field')::numeric <= :it", Field.lessOrEqual("le_field", 18, ":it").withQualifier("q").toWhere(), "Field WHERE clause not generated correctly") } @Test - @DisplayName("toWhere generates parameter w/ qualifier (SQLite)") + @DisplayName("toWhere generates parameter w/ qualifier | SQLite") fun toWhereParamWithQualSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("q.data->>'le_field' <= :it", Field.lessOrEqual("le_field", 18, ":it").withQualifier("q").toWhere(), "Field WHERE clause not generated correctly") diff --git a/src/jvm/src/test/kotlin/query/WhereTest.kt b/src/jvm/src/test/kotlin/query/WhereTest.kt index 95d68d8..c436ec8 100644 --- a/src/jvm/src/test/kotlin/query/WhereTest.kt +++ b/src/jvm/src/test/kotlin/query/WhereTest.kt @@ -5,6 +5,7 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import solutions.bitbadger.documents.* +import solutions.bitbadger.documents.support.ForceDialect import kotlin.test.assertEquals /** @@ -18,7 +19,7 @@ class WhereTest { */ @AfterEach fun cleanUp() { - Configuration.dialectValue = null + ForceDialect.none() } @Test @@ -27,30 +28,30 @@ class WhereTest { assertEquals("", Where.byFields(listOf())) @Test - @DisplayName("byFields generates one numeric field (PostgreSQL)") + @DisplayName("byFields generates one numeric field | PostgreSQL") fun byFieldsOneFieldPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(data->>'it')::numeric = :that", Where.byFields(listOf(Field.equal("it", 9, ":that")))) } @Test - @DisplayName("byFields generates one alphanumeric field (PostgreSQL)") + @DisplayName("byFields generates one alphanumeric field | PostgreSQL") fun byFieldsOneAlphaFieldPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'it' = :that", Where.byFields(listOf(Field.equal("it", "", ":that")))) } @Test - @DisplayName("byFields generates one field (SQLite)") + @DisplayName("byFields generates one field | SQLite") fun byFieldsOneFieldSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'it' = :that", Where.byFields(listOf(Field.equal("it", "", ":that")))) } @Test - @DisplayName("byFields generates multiple fields w/ default match (PostgreSQL)") + @DisplayName("byFields generates multiple fields w/ default match | PostgreSQL") fun byFieldsMultipleDefaultPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals( "data->>'1' = :one AND (data->>'2')::numeric = :two AND data->>'3' = :three", Where.byFields( @@ -60,9 +61,9 @@ class WhereTest { } @Test - @DisplayName("byFields generates multiple fields w/ default match (SQLite)") + @DisplayName("byFields generates multiple fields w/ default match | SQLite") fun byFieldsMultipleDefaultSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals( "data->>'1' = :one AND data->>'2' = :two AND data->>'3' = :three", Where.byFields( @@ -72,9 +73,9 @@ class WhereTest { } @Test - @DisplayName("byFields generates multiple fields w/ ANY match (PostgreSQL)") + @DisplayName("byFields generates multiple fields w/ ANY match | PostgreSQL") fun byFieldsMultipleAnyPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals( "data->>'1' = :one OR (data->>'2')::numeric = :two OR data->>'3' = :three", Where.byFields( @@ -85,9 +86,9 @@ class WhereTest { } @Test - @DisplayName("byFields generates multiple fields w/ ANY match (SQLite)") + @DisplayName("byFields generates multiple fields w/ ANY match | SQLite") fun byFieldsMultipleAnySQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals( "data->>'1' = :one OR data->>'2' = :two OR data->>'3' = :three", Where.byFields( @@ -98,79 +99,79 @@ class WhereTest { } @Test - @DisplayName("byId generates defaults for alphanumeric key (PostgreSQL)") + @DisplayName("byId generates defaults for alphanumeric key | PostgreSQL") fun byIdDefaultAlphaPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'id' = :id", Where.byId(docId = "")) } @Test - @DisplayName("byId generates defaults for numeric key (PostgreSQL)") + @DisplayName("byId generates defaults for numeric key | PostgreSQL") fun byIdDefaultNumericPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("(data->>'id')::numeric = :id", Where.byId(docId = 5)) } @Test - @DisplayName("byId generates defaults (SQLite)") + @DisplayName("byId generates defaults | SQLite") fun byIdDefaultSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'id' = :id", Where.byId(docId = "")) } @Test - @DisplayName("byId generates named ID (PostgreSQL)") + @DisplayName("byId generates named ID | PostgreSQL") fun byIdDefaultNamedPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data->>'id' = :key", Where.byId(":key")) } @Test - @DisplayName("byId generates named ID (SQLite)") + @DisplayName("byId generates named ID | SQLite") fun byIdDefaultNamedSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertEquals("data->>'id' = :key", Where.byId(":key")) } @Test - @DisplayName("jsonContains generates defaults (PostgreSQL)") + @DisplayName("jsonContains generates defaults | PostgreSQL") fun jsonContainsDefaultPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data @> :criteria", Where.jsonContains()) } @Test - @DisplayName("jsonContains generates named parameter (PostgreSQL)") + @DisplayName("jsonContains generates named parameter | PostgreSQL") fun jsonContainsNamedPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("data @> :it", Where.jsonContains(":it")) } @Test - @DisplayName("jsonContains fails (SQLite)") + @DisplayName("jsonContains fails | SQLite") fun jsonContainsFailsSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertThrows { Where.jsonContains() } } @Test - @DisplayName("jsonPathMatches generates defaults (PostgreSQL)") + @DisplayName("jsonPathMatches generates defaults | PostgreSQL") fun jsonPathMatchDefaultPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("jsonb_path_exists(data, :path::jsonpath)", Where.jsonPathMatches()) } @Test - @DisplayName("jsonPathMatches generates named parameter (PostgreSQL)") + @DisplayName("jsonPathMatches generates named parameter | PostgreSQL") fun jsonPathMatchNamedPostgres() { - Configuration.dialectValue = Dialect.POSTGRESQL + ForceDialect.postgres() assertEquals("jsonb_path_exists(data, :jp::jsonpath)", Where.jsonPathMatches(":jp")) } @Test - @DisplayName("jsonPathMatches fails (SQLite)") + @DisplayName("jsonPathMatches fails | SQLite") fun jsonPathFailsSQLite() { - Configuration.dialectValue = Dialect.SQLITE + ForceDialect.sqlite() assertThrows { Where.jsonPathMatches() } } }