Initial Development #1
@ -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)
|
||||
}
|
||||
|
@ -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,6 +21,8 @@ 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
|
||||
|
@ -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)
|
||||
class DocumentException @JvmOverloads constructor(message: String, cause: Throwable? = null) : Exception(message, cause)
|
||||
|
@ -118,7 +118,6 @@ class Field<T> private constructor(
|
||||
|
||||
is ComparisonInArray<*> -> {
|
||||
val mkString = Configuration.dialect("append parameters for InArray") == Dialect.POSTGRESQL
|
||||
// TODO: I think this is actually Pair<String, Collection<*>>
|
||||
comparison.value.second.forEachIndexed { index, item ->
|
||||
if (mkString) {
|
||||
existing.add(Parameter("${parameterName}_$index", ParameterType.STRING, "$item"))
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"),
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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<T>(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<T>(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})"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -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 <TDoc> Connection.customList(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
@ -34,7 +37,9 @@ fun <TDoc> 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 <TDoc> Connection.customSingle(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
@ -48,7 +53,9 @@ fun <TDoc> 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<Parameter<*>> = listOf()) =
|
||||
Custom.nonQuery(query, parameters, this)
|
||||
|
||||
@ -60,7 +67,9 @@ fun Connection.customNonQuery(query: String, parameters: Collection<Parameter<*>
|
||||
* @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 <T : Any> Connection.customScalar(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
@ -109,7 +118,7 @@ fun Connection.ensureDocumentIndex(tableName: String, indexType: DocumentIndex)
|
||||
* @param document The document to be inserted
|
||||
*/
|
||||
fun <TDoc> Connection.insert(tableName: String, document: TDoc) =
|
||||
Document.insert<TDoc>(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 <TKey, TDoc> 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<Field<*>>, howMatched: FieldMatch? = null) =
|
||||
Count.byFields(tableName, fields, howMatched, this)
|
||||
|
@ -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<Field<*>>, 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 <TContains> 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 <TContains> 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) }
|
||||
|
@ -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 <TDoc> 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 <TDoc> 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 <TDoc> 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 <TDoc> 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<Parameter<*>> = 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<Parameter<*>> = 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 <T : Any> 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 <T : Any> scalar(
|
||||
query: String,
|
||||
parameters: Collection<Parameter<*>> = listOf(),
|
||||
|
@ -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<String>, 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<String>) =
|
||||
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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
@ -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<String>(":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<String>(":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<DocumentException> { 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<DocumentException> { Where.jsonPathMatches() }
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user