Initial Development #1
@ -3,6 +3,7 @@
|
|||||||
<component name="AdditionalModuleElements">
|
<component name="AdditionalModuleElements">
|
||||||
<content url="file://$MODULE_DIR$" dumb="true">
|
<content url="file://$MODULE_DIR$" dumb="true">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/integration-test/kotlin" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/src/integration-test/kotlin" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
</content>
|
</content>
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
10
pom.xml
10
pom.xml
@ -38,7 +38,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<kotlin.code.style>official</kotlin.code.style>
|
<kotlin.code.style>official</kotlin.code.style>
|
||||||
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
|
<kotlin.compiler.jvmTarget>11</kotlin.compiler.jvmTarget>
|
||||||
<kotlin.version>2.1.0</kotlin.version>
|
<kotlin.version>2.1.0</kotlin.version>
|
||||||
<serialization.version>1.8.0</serialization.version>
|
<serialization.version>1.8.0</serialization.version>
|
||||||
</properties>
|
</properties>
|
||||||
@ -111,6 +111,14 @@
|
|||||||
<mainClass>MainKt</mainClass>
|
<mainClass>MainKt</mainClass>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>9</source>
|
||||||
|
<target>9</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package solutions.bitbadger.documents
|
package solutions.bitbadger.documents
|
||||||
|
|
||||||
|
import kotlin.jvm.Throws
|
||||||
import kotlin.reflect.full.*
|
import kotlin.reflect.full.*
|
||||||
|
import kotlin.reflect.jvm.isAccessible
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Strategies for automatic document IDs
|
* Strategies for automatic document IDs
|
||||||
@ -22,7 +24,7 @@ enum class AutoId {
|
|||||||
*
|
*
|
||||||
* @return A `UUID` string
|
* @return A `UUID` string
|
||||||
*/
|
*/
|
||||||
fun generateUUID(): String =
|
@JvmStatic fun generateUUID(): String =
|
||||||
java.util.UUID.randomUUID().toString().replace("-", "")
|
java.util.UUID.randomUUID().toString().replace("-", "")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +33,7 @@ enum class AutoId {
|
|||||||
* @param length The length of the string (optional; defaults to configured length)
|
* @param length The length of the string (optional; defaults to configured length)
|
||||||
* @return A string of random hex characters of the requested length
|
* @return A string of random hex characters of the requested length
|
||||||
*/
|
*/
|
||||||
fun generateRandomString(length: Int? = null): String =
|
@JvmStatic fun generateRandomString(length: Int? = null): String =
|
||||||
(length ?: Configuration.idStringLength).let { len ->
|
(length ?: Configuration.idStringLength).let { len ->
|
||||||
kotlin.random.Random.nextBytes((len + 2) / 2)
|
kotlin.random.Random.nextBytes((len + 2) / 2)
|
||||||
.joinToString("") { String.format("%02x", it) }
|
.joinToString("") { String.format("%02x", it) }
|
||||||
@ -47,12 +49,13 @@ enum class AutoId {
|
|||||||
* @return `true` if the document needs an automatic ID, `false` if not
|
* @return `true` if the document needs an automatic ID, `false` if not
|
||||||
* @throws DocumentException If bad input prevents the determination
|
* @throws DocumentException If bad input prevents the determination
|
||||||
*/
|
*/
|
||||||
fun <T> needsAutoId(strategy: AutoId, document: T, idProp: String): Boolean {
|
@Throws(DocumentException::class)
|
||||||
|
@JvmStatic fun <T> needsAutoId(strategy: AutoId, document: T, idProp: String): Boolean {
|
||||||
if (document == null) throw DocumentException("document cannot be null")
|
if (document == null) throw DocumentException("document cannot be null")
|
||||||
|
|
||||||
if (strategy == DISABLED) return false;
|
if (strategy == DISABLED) return false
|
||||||
|
|
||||||
val id = document!!::class.memberProperties.find { it.name == idProp }
|
val id = document!!::class.memberProperties.find { it.name == idProp }?.apply { isAccessible = true }
|
||||||
if (id == null) throw DocumentException("$idProp not found in document")
|
if (id == null) throw DocumentException("$idProp not found in document")
|
||||||
|
|
||||||
if (strategy == NUMBER) {
|
if (strategy == NUMBER) {
|
||||||
@ -65,11 +68,12 @@ enum class AutoId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.returnType == String::class.createType()) {
|
val typ = id.returnType.toString()
|
||||||
|
if (typ.endsWith("String") || typ.endsWith("String!")) {
|
||||||
return id.call(document) == ""
|
return id.call(document) == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
throw DocumentException("$idProp was not a string; cannot auto-generate UUID or random string")
|
throw DocumentException("$idProp was not a string ($typ); cannot auto-generate UUID or random string")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package solutions.bitbadger.documents
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import java.sql.Connection
|
import java.sql.Connection
|
||||||
import java.sql.DriverManager
|
import java.sql.DriverManager
|
||||||
|
import kotlin.jvm.Throws
|
||||||
|
|
||||||
object Configuration {
|
object Configuration {
|
||||||
|
|
||||||
@ -12,25 +13,33 @@ object Configuration {
|
|||||||
* The default sets `encodeDefaults` to `true` and `explicitNulls` to `false`; see
|
* The default sets `encodeDefaults` to `true` and `explicitNulls` to `false`; see
|
||||||
* https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md for all configuration options
|
* https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/json.md for all configuration options
|
||||||
*/
|
*/
|
||||||
|
@JvmField
|
||||||
var json = Json {
|
var json = Json {
|
||||||
encodeDefaults = true
|
encodeDefaults = true
|
||||||
explicitNulls = false
|
explicitNulls = false
|
||||||
coerceInputValues = true
|
coerceInputValues = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The field in which a document's ID is stored */
|
/** The field in which a document's ID is stored */
|
||||||
|
@JvmField
|
||||||
var idField = "id"
|
var idField = "id"
|
||||||
|
|
||||||
/** The automatic ID strategy to use */
|
/** The automatic ID strategy to use */
|
||||||
|
@JvmField
|
||||||
var autoIdStrategy = AutoId.DISABLED
|
var autoIdStrategy = AutoId.DISABLED
|
||||||
|
|
||||||
/** The length of automatic random hex character string */
|
/** The length of automatic random hex character string */
|
||||||
|
@JvmField
|
||||||
var idStringLength = 16
|
var idStringLength = 16
|
||||||
|
|
||||||
|
/** The JSON serializer to use for documents */
|
||||||
|
var serializer: DocumentSerializer = DocumentSerializerKotlin()
|
||||||
|
|
||||||
/** The derived dialect value from the connection string */
|
/** The derived dialect value from the connection string */
|
||||||
internal var dialectValue: Dialect? = null
|
internal var dialectValue: Dialect? = null
|
||||||
|
|
||||||
/** The connection string for the JDBC connection */
|
/** The connection string for the JDBC connection */
|
||||||
|
@JvmStatic
|
||||||
var connectionString: String? = null
|
var connectionString: String? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
@ -43,6 +52,7 @@ object Configuration {
|
|||||||
* @return 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 IllegalArgumentException If the connection string is not set before calling this
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun dbConn(): Connection {
|
fun dbConn(): Connection {
|
||||||
if (connectionString == null) {
|
if (connectionString == null) {
|
||||||
throw IllegalArgumentException("Please provide a connection string before attempting data access")
|
throw IllegalArgumentException("Please provide a connection string before attempting data access")
|
||||||
@ -57,7 +67,11 @@ object Configuration {
|
|||||||
* @return The dialect for the current connection
|
* @return The dialect for the current connection
|
||||||
* @throws DocumentException If the dialect has not been set
|
* @throws DocumentException If the dialect has not been set
|
||||||
*/
|
*/
|
||||||
|
@Throws(DocumentException::class)
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun dialect(process: String? = null): Dialect =
|
fun dialect(process: String? = null): Dialect =
|
||||||
dialectValue ?: throw DocumentException(
|
dialectValue ?: throw DocumentException(
|
||||||
"Database mode not set" + if (process == null) "" else "; cannot $process")
|
"Database mode not set" + if (process == null) "" else "; cannot $process"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -69,18 +69,18 @@ class Field<T> private constructor(
|
|||||||
if (parameterName == null && !listOf(Op.EXISTS, Op.NOT_EXISTS).contains(comparison.op))
|
if (parameterName == null && !listOf(Op.EXISTS, Op.NOT_EXISTS).contains(comparison.op))
|
||||||
throw DocumentException("Parameter for $name must be specified")
|
throw DocumentException("Parameter for $name must be specified")
|
||||||
|
|
||||||
val dialect = Configuration.dialect("make field WHERE clause")
|
val dialect = Configuration.dialect("make field WHERE clause")
|
||||||
val fieldName = path(dialect, if (comparison.op == Op.IN_ARRAY) FieldFormat.JSON else FieldFormat.SQL)
|
val fieldName = path(dialect, if (comparison.op == Op.IN_ARRAY) FieldFormat.JSON else FieldFormat.SQL)
|
||||||
val fieldPath = when (dialect) {
|
val fieldPath = when (dialect) {
|
||||||
Dialect.POSTGRESQL -> if (comparison.isNumeric) "($fieldName)::numeric" else fieldName
|
Dialect.POSTGRESQL -> if (comparison.isNumeric) "($fieldName)::numeric" else fieldName
|
||||||
Dialect.SQLITE -> fieldName
|
Dialect.SQLITE -> fieldName
|
||||||
}
|
}
|
||||||
val criteria = when (comparison.op) {
|
val criteria = when (comparison.op) {
|
||||||
in listOf(Op.EXISTS, Op.NOT_EXISTS) -> ""
|
in listOf(Op.EXISTS, Op.NOT_EXISTS) -> ""
|
||||||
Op.BETWEEN -> " ${parameterName}min AND ${parameterName}max"
|
Op.BETWEEN -> " ${parameterName}min AND ${parameterName}max"
|
||||||
Op.IN -> " ($inParameterNames)"
|
Op.IN -> " ($inParameterNames)"
|
||||||
Op.IN_ARRAY -> if (dialect == Dialect.POSTGRESQL) " ARRAY[$inParameterNames]" else ""
|
Op.IN_ARRAY -> if (dialect == Dialect.POSTGRESQL) " ARRAY[$inParameterNames]" else ""
|
||||||
else -> " $parameterName"
|
else -> " $parameterName"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@ -134,7 +134,7 @@ class Field<T> private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"Field ${parameterName ?: "<unnamed>"} $comparison${qualifier?.let { " (qualifier $it)"} ?: ""}"
|
"Field ${parameterName ?: "<unnamed>"} $comparison${qualifier?.let { " (qualifier $it)" } ?: ""}"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@ -146,6 +146,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> equal(name: String, value: T, paramName: String? = null) =
|
fun <T> equal(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.EQUAL, value), paramName)
|
||||||
|
|
||||||
@ -157,6 +159,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> greater(name: String, value: T, paramName: String? = null) =
|
fun <T> greater(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.GREATER, value), paramName)
|
Field(name, ComparisonSingle(Op.GREATER, value), paramName)
|
||||||
|
|
||||||
@ -168,6 +172,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> greaterOrEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> greaterOrEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.GREATER_OR_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.GREATER_OR_EQUAL, value), paramName)
|
||||||
|
|
||||||
@ -179,6 +185,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> less(name: String, value: T, paramName: String? = null) =
|
fun <T> less(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.LESS, value), paramName)
|
Field(name, ComparisonSingle(Op.LESS, value), paramName)
|
||||||
|
|
||||||
@ -190,6 +198,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> lessOrEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> lessOrEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.LESS_OR_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.LESS_OR_EQUAL, value), paramName)
|
||||||
|
|
||||||
@ -201,6 +211,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> notEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> notEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonSingle(Op.NOT_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.NOT_EQUAL, value), paramName)
|
||||||
|
|
||||||
@ -213,6 +225,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> between(name: String, minValue: T, maxValue: T, paramName: String? = null) =
|
fun <T> between(name: String, minValue: T, maxValue: T, paramName: String? = null) =
|
||||||
Field(name, ComparisonBetween(Pair(minValue, maxValue)), paramName)
|
Field(name, ComparisonBetween(Pair(minValue, maxValue)), paramName)
|
||||||
|
|
||||||
@ -224,6 +238,8 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> any(name: String, values: Collection<T>, paramName: String? = null) =
|
fun <T> any(name: String, values: Collection<T>, paramName: String? = null) =
|
||||||
Field(name, ComparisonIn(values), paramName)
|
Field(name, ComparisonIn(values), paramName)
|
||||||
|
|
||||||
@ -236,18 +252,50 @@ class Field<T> private constructor(
|
|||||||
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
* @param paramName The parameter name for the field (optional, defaults to auto-generated)
|
||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun <T> inArray(name: String, tableName: String, values: Collection<T>, paramName: String? = null) =
|
fun <T> inArray(name: String, tableName: String, values: Collection<T>, paramName: String? = null) =
|
||||||
Field(name, ComparisonInArray(Pair(tableName, values)), paramName)
|
Field(name, ComparisonInArray(Pair(tableName, values)), paramName)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a field where a document field should exist
|
||||||
|
*
|
||||||
|
* @param name The name of the field whose existence should be checked
|
||||||
|
* @return A `Field` with the given comparison
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun exists(name: String) =
|
fun exists(name: String) =
|
||||||
Field(name, ComparisonSingle(Op.EXISTS, ""))
|
Field(name, ComparisonSingle(Op.EXISTS, ""))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a field where a document field should not exist
|
||||||
|
*
|
||||||
|
* @param name The name of the field whose existence should be checked
|
||||||
|
* @return A `Field` with the given comparison
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun notExists(name: String) =
|
fun notExists(name: String) =
|
||||||
Field(name, ComparisonSingle(Op.NOT_EXISTS, ""))
|
Field(name, ComparisonSingle(Op.NOT_EXISTS, ""))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a field with a given named comparison (useful for ordering fields)
|
||||||
|
*
|
||||||
|
* @param name The name of the field
|
||||||
|
* @return A `Field` with the given name (comparison equal to an empty string)
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun named(name: String) =
|
fun named(name: String) =
|
||||||
Field(name, ComparisonSingle(Op.EQUAL, ""))
|
Field(name, ComparisonSingle(Op.EQUAL, ""))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a name to the SQL path for the given dialect
|
||||||
|
*
|
||||||
|
* @param name The field name to be translated
|
||||||
|
* @param dialect The database for which the path should be created
|
||||||
|
* @param format Whether the field should be retrieved as a JSON value or a SQL value
|
||||||
|
* @return The path to the JSON field
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun nameToPath(name: String, dialect: Dialect, format: FieldFormat): String {
|
fun nameToPath(name: String, dialect: Dialect, format: FieldFormat): String {
|
||||||
val path = StringBuilder("data")
|
val path = StringBuilder("data")
|
||||||
val extra = if (format == FieldFormat.SQL) ">" else ""
|
val extra = if (format == FieldFormat.SQL) ">" else ""
|
||||||
|
@ -3,6 +3,7 @@ package solutions.bitbadger.documents
|
|||||||
import java.sql.Connection
|
import java.sql.Connection
|
||||||
import java.sql.PreparedStatement
|
import java.sql.PreparedStatement
|
||||||
import java.sql.SQLException
|
import java.sql.SQLException
|
||||||
|
import kotlin.jvm.Throws
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Functions to assist with the creation and implementation of parameters for SQL queries
|
* Functions to assist with the creation and implementation of parameters for SQL queries
|
||||||
@ -17,6 +18,7 @@ object Parameters {
|
|||||||
* @param fields The collection of fields to be named
|
* @param fields The collection of fields to be named
|
||||||
* @return The collection of fields with parameter names assigned
|
* @return The collection of fields with parameter names assigned
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun nameFields(fields: Collection<Field<*>>): Collection<Field<*>> {
|
fun nameFields(fields: Collection<Field<*>>): Collection<Field<*>> {
|
||||||
val name = ParameterName()
|
val name = ParameterName()
|
||||||
return fields.map {
|
return fields.map {
|
||||||
@ -45,6 +47,7 @@ object Parameters {
|
|||||||
* @param existing Any existing parameters for the query (optional, defaults to empty collection)
|
* @param existing Any existing parameters for the query (optional, defaults to empty collection)
|
||||||
* @return A collection of parameters for the query
|
* @return A collection of parameters for the query
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun addFields(fields: Collection<Field<*>>, existing: MutableCollection<Parameter<*>> = mutableListOf()) =
|
fun addFields(fields: Collection<Field<*>>, existing: MutableCollection<Parameter<*>> = mutableListOf()) =
|
||||||
fields.fold(existing) { acc, field -> field.appendParameter(acc) }
|
fields.fold(existing) { acc, field -> field.appendParameter(acc) }
|
||||||
|
|
||||||
@ -55,6 +58,7 @@ object Parameters {
|
|||||||
* @param parameters The parameters for the query
|
* @param parameters The parameters for the query
|
||||||
* @return The query, with name parameters changed to `?`s
|
* @return The query, with name parameters changed to `?`s
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun replaceNamesInQuery(query: String, parameters: Collection<Parameter<*>>) =
|
fun replaceNamesInQuery(query: String, parameters: Collection<Parameter<*>>) =
|
||||||
parameters.sortedByDescending { it.name.length }.fold(query) { acc, param -> acc.replace(param.name, "?") }
|
parameters.sortedByDescending { it.name.length }.fold(query) { acc, param -> acc.replace(param.name, "?") }
|
||||||
|
|
||||||
@ -67,6 +71,8 @@ object Parameters {
|
|||||||
* @return A `PreparedStatement` with the parameter names replaced with `?` and parameter values bound
|
* @return A `PreparedStatement` with the parameter names replaced with `?` and parameter values bound
|
||||||
* @throws DocumentException If parameter names are invalid or number value types are invalid
|
* @throws DocumentException If parameter names are invalid or number value types are invalid
|
||||||
*/
|
*/
|
||||||
|
@Throws(DocumentException::class)
|
||||||
|
@JvmStatic
|
||||||
fun apply(conn: Connection, query: String, parameters: Collection<Parameter<*>>): PreparedStatement {
|
fun apply(conn: Connection, query: String, parameters: Collection<Parameter<*>>): PreparedStatement {
|
||||||
|
|
||||||
if (parameters.isEmpty()) return try {
|
if (parameters.isEmpty()) return try {
|
||||||
@ -105,6 +111,8 @@ object Parameters {
|
|||||||
* @param parameterName The parameter name to use for the query
|
* @param parameterName The parameter name to use for the query
|
||||||
* @return A list of parameters to use for building the query
|
* @return A list of parameters to use for building the query
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
@JvmOverloads
|
||||||
fun fieldNames(names: Collection<String>, parameterName: String = ":name"): MutableCollection<Parameter<*>> =
|
fun fieldNames(names: Collection<String>, parameterName: String = ":name"): MutableCollection<Parameter<*>> =
|
||||||
when (Configuration.dialect("generate field name parameters")) {
|
when (Configuration.dialect("generate field name parameters")) {
|
||||||
Dialect.POSTGRESQL -> mutableListOf(
|
Dialect.POSTGRESQL -> mutableListOf(
|
||||||
|
217
src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java
Normal file
217
src/test/java/solutions/bitbadger/documents/java/AutoIdTest.java
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.AutoId;
|
||||||
|
import solutions.bitbadger.documents.DocumentException;
|
||||||
|
import solutions.bitbadger.documents.java.testDocs.*;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `AutoId` enum
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | AutoId")
|
||||||
|
final public class AutoIdTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Generates a UUID string")
|
||||||
|
public void generateUUID() {
|
||||||
|
assertEquals(32, AutoId.generateUUID().length(), "The UUID should have been a 32-character string");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Generates a random hex character string of an even length")
|
||||||
|
public void generateRandomStringEven() {
|
||||||
|
final String result = AutoId.generateRandomString(8);
|
||||||
|
assertEquals(8, result.length(), "There should have been 8 characters in " + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Generates a random hex character string of an odd length")
|
||||||
|
public void generateRandomStringOdd() {
|
||||||
|
final String result = AutoId.generateRandomString(11);
|
||||||
|
assertEquals(11, result.length(), "There should have been 11 characters in " + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Generates different random hex character strings")
|
||||||
|
public void generateRandomStringIsRandom() {
|
||||||
|
final String result1 = AutoId.generateRandomString(16);
|
||||||
|
final String result2 = AutoId.generateRandomString(16);
|
||||||
|
assertNotEquals(result1, result2, "There should have been 2 different strings generated");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId fails for null document")
|
||||||
|
public void needsAutoIdFailsForNullDocument() {
|
||||||
|
assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.DISABLED, null, "id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId fails for missing ID property")
|
||||||
|
public void needsAutoIdFailsForMissingId() {
|
||||||
|
assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.UUID, new IntIdClass(0), "Id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false if disabled")
|
||||||
|
public void needsAutoIdFalseIfDisabled() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.DISABLED, "", ""), "Disabled Auto ID should always return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for Number strategy and byte ID of 0")
|
||||||
|
public void needsAutoIdTrueForByteWithZero() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 0), "id"),
|
||||||
|
"Number Auto ID with 0 should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0")
|
||||||
|
public void needsAutoIdFalseForByteWithNonZero() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ByteIdClass((byte) 77), "id"),
|
||||||
|
"Number Auto ID with 77 should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for Number strategy and short ID of 0")
|
||||||
|
public void needsAutoIdTrueForShortWithZero() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 0), "id"),
|
||||||
|
"Number Auto ID with 0 should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for Number strategy and short ID of non-0")
|
||||||
|
public void needsAutoIdFalseForShortWithNonZero() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new ShortIdClass((short) 31), "id"),
|
||||||
|
"Number Auto ID with 31 should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for Number strategy and int ID of 0")
|
||||||
|
public void needsAutoIdTrueForIntWithZero() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(0), "id"),
|
||||||
|
"Number Auto ID with 0 should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for Number strategy and int ID of non-0")
|
||||||
|
public void needsAutoIdFalseForIntWithNonZero() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new IntIdClass(6), "id"),
|
||||||
|
"Number Auto ID with 6 should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for Number strategy and long ID of 0")
|
||||||
|
public void needsAutoIdTrueForLongWithZero() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(0L), "id"),
|
||||||
|
"Number Auto ID with 0 should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for Number strategy and long ID of non-0")
|
||||||
|
public void needsAutoIdFalseForLongWithNonZero() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, new LongIdClass(2L), "id"),
|
||||||
|
"Number Auto ID with 2 should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId fails for Number strategy and non-number ID")
|
||||||
|
public void needsAutoIdFailsForNumberWithStringId() {
|
||||||
|
assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.NUMBER, new StringIdClass(""), "id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for UUID strategy and blank ID")
|
||||||
|
public void needsAutoIdTrueForUUIDWithBlank() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.UUID, new StringIdClass(""), "id"),
|
||||||
|
"UUID Auto ID with blank should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for UUID strategy and non-blank ID")
|
||||||
|
public void needsAutoIdFalseForUUIDNotBlank() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.UUID, new StringIdClass("howdy"), "id"),
|
||||||
|
"UUID Auto ID with non-blank should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId fails for UUID strategy and non-string ID")
|
||||||
|
public void needsAutoIdFailsForUUIDNonString() {
|
||||||
|
assertThrows(DocumentException.class, () -> AutoId.needsAutoId(AutoId.UUID, new IntIdClass(5), "id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns true for Random String strategy and blank ID")
|
||||||
|
public void needsAutoIdTrueForRandomWithBlank() {
|
||||||
|
try {
|
||||||
|
assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass(""), "id"),
|
||||||
|
"Random String Auto ID with blank should return true");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId returns false for Random String strategy and non-blank ID")
|
||||||
|
public void needsAutoIdFalseForRandomNotBlank() {
|
||||||
|
try {
|
||||||
|
assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, new StringIdClass("full"), "id"),
|
||||||
|
"Random String Auto ID with non-blank should return false");
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("needsAutoId fails for Random String strategy and non-string ID")
|
||||||
|
public void needsAutoIdFailsForRandomNonString() {
|
||||||
|
assertThrows(DocumentException.class,
|
||||||
|
() -> AutoId.needsAutoId(AutoId.RANDOM_STRING, new ShortIdClass((short) 55), "id"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.*;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `Configuration` object
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | Configuration")
|
||||||
|
final public class ConfigurationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Default JSON options are as expected")
|
||||||
|
public void defaultJsonOptions() {
|
||||||
|
assertTrue(Configuration.json.getConfiguration().getEncodeDefaults(), "Encode Defaults should have been set");
|
||||||
|
assertFalse(Configuration.json.getConfiguration().getExplicitNulls(),
|
||||||
|
"Explicit Nulls should not have been set");
|
||||||
|
assertTrue(Configuration.json.getConfiguration().getCoerceInputValues(),
|
||||||
|
"Coerce Input Values should have been set");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Default ID field is `id`")
|
||||||
|
public void defaultIdField() {
|
||||||
|
assertEquals("id", Configuration.idField, "Default ID field incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Default Auto ID strategy is `DISABLED`")
|
||||||
|
public void defaultAutoId() {
|
||||||
|
assertEquals(AutoId.DISABLED, Configuration.autoIdStrategy, "Default Auto ID strategy should be `disabled`");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Default ID string length should be 16")
|
||||||
|
public void defaultIdStringLength() {
|
||||||
|
assertEquals(16, Configuration.idStringLength, "Default ID string length should be 16");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Dialect is derived from connection string")
|
||||||
|
public void dialectIsDerived() {
|
||||||
|
try {
|
||||||
|
assertThrows(DocumentException.class, Configuration::dialect);
|
||||||
|
Configuration.setConnectionString("jdbc:postgresql:db");
|
||||||
|
assertEquals(Dialect.POSTGRESQL, Configuration.dialect());
|
||||||
|
} catch (DocumentException ex) {
|
||||||
|
fail(ex);
|
||||||
|
} finally {
|
||||||
|
Configuration.setConnectionString(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.DocumentIndex;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `DocumentIndex` enum
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | DocumentIndex")
|
||||||
|
final public class DocumentIndexTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("FULL uses proper SQL")
|
||||||
|
public void fullSQL() {
|
||||||
|
assertEquals("", DocumentIndex.FULL.getSql(), "The SQL for Full is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("OPTIMIZED uses proper SQL")
|
||||||
|
public void optimizedSQL() {
|
||||||
|
assertEquals(" jsonb_path_ops", DocumentIndex.OPTIMIZED.getSql(), "The SQL for Optimized is incorrect");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.FieldMatch;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `FieldMatch` enum
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | FieldMatch")
|
||||||
|
final public class FieldMatchTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ANY uses proper SQL")
|
||||||
|
public void any() {
|
||||||
|
assertEquals("OR", FieldMatch.ANY.getSql(), "ANY should use OR");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("ALL uses proper SQL")
|
||||||
|
public void all() {
|
||||||
|
assertEquals("AND", FieldMatch.ALL.getSql(), "ALL should use AND");
|
||||||
|
}
|
||||||
|
}
|
629
src/test/java/solutions/bitbadger/documents/java/FieldTest.java
Normal file
629
src/test/java/solutions/bitbadger/documents/java/FieldTest.java
Normal file
@ -0,0 +1,629 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import kotlin.Pair;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.*;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `Field` class
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | Field")
|
||||||
|
final public class FieldTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the connection string (resets Dialect)
|
||||||
|
*/
|
||||||
|
@AfterEach
|
||||||
|
public void cleanUp() {
|
||||||
|
Configuration.setConnectionString(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~ INSTANCE METHODS ~~~
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("withParameterName fails for invalid name")
|
||||||
|
public void withParamNameFails() {
|
||||||
|
assertThrows(DocumentException.class, () -> Field.equal("it", "").withParameterName("2424"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("withParameterName works with colon prefix")
|
||||||
|
public void withParamNameColon() {
|
||||||
|
Field<String> field = Field.equal("abc", "22").withQualifier("me");
|
||||||
|
Field<String> withParam = field.withParameterName(":test");
|
||||||
|
assertNotSame(field, withParam, "A new Field instance should have been created");
|
||||||
|
assertEquals(field.getName(), withParam.getName(), "Name should have been preserved");
|
||||||
|
assertEquals(field.getComparison(), withParam.getComparison(), "Comparison should have been preserved");
|
||||||
|
assertEquals(":test", withParam.getParameterName(), "Parameter name not set correctly");
|
||||||
|
assertEquals(field.getQualifier(), withParam.getQualifier(), "Qualifier should have been preserved");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("withParameterName works with at-sign prefix")
|
||||||
|
public void withParamNameAtSign() {
|
||||||
|
Field<String> field = Field.equal("def", "44");
|
||||||
|
Field<String> withParam = field.withParameterName("@unit");
|
||||||
|
assertNotSame(field, withParam, "A new Field instance should have been created");
|
||||||
|
assertEquals(field.getName(), withParam.getName(), "Name should have been preserved");
|
||||||
|
assertEquals(field.getComparison(), withParam.getComparison(), "Comparison should have been preserved");
|
||||||
|
assertEquals("@unit", withParam.getParameterName(), "Parameter name not set correctly");
|
||||||
|
assertEquals(field.getQualifier(), withParam.getQualifier(), "Qualifier should have been preserved");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("withQualifier sets qualifier correctly")
|
||||||
|
public void withQualifier() {
|
||||||
|
Field<String> field = Field.equal("j", "k");
|
||||||
|
Field<String> withQual = field.withQualifier("test");
|
||||||
|
assertNotSame(field, withQual, "A new Field instance should have been created");
|
||||||
|
assertEquals(field.getName(), withQual.getName(), "Name should have been preserved");
|
||||||
|
assertEquals(field.getComparison(), withQual.getComparison(), "Comparison should have been preserved");
|
||||||
|
assertEquals(field.getParameterName(), withQual.getParameterName(),
|
||||||
|
"Parameter Name should have been preserved");
|
||||||
|
assertEquals("test", withQual.getQualifier(), "Qualifier not set correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for simple unqualified PostgreSQL field")
|
||||||
|
public void pathPostgresSimpleUnqualified() {
|
||||||
|
assertEquals("data->>'SomethingCool'",
|
||||||
|
Field.greaterOrEqual("SomethingCool", 18).path(Dialect.POSTGRESQL, FieldFormat.SQL),
|
||||||
|
"Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for simple qualified PostgreSQL field")
|
||||||
|
public void pathPostgresSimpleQualified() {
|
||||||
|
assertEquals("this.data->>'SomethingElse'",
|
||||||
|
Field.less("SomethingElse", 9).withQualifier("this").path(Dialect.POSTGRESQL, FieldFormat.SQL),
|
||||||
|
"Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for nested unqualified PostgreSQL field")
|
||||||
|
public void pathPostgresNestedUnqualified() {
|
||||||
|
assertEquals("data#>>'{My,Nested,Field}'",
|
||||||
|
Field.equal("My.Nested.Field", "howdy").path(Dialect.POSTGRESQL, FieldFormat.SQL), "Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for nested qualified PostgreSQL field")
|
||||||
|
public void pathPostgresNestedQualified() {
|
||||||
|
assertEquals("bird.data#>>'{Nest,Away}'",
|
||||||
|
Field.equal("Nest.Away", "doc").withQualifier("bird").path(Dialect.POSTGRESQL, FieldFormat.SQL),
|
||||||
|
"Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for simple unqualified SQLite field")
|
||||||
|
public void pathSQLiteSimpleUnqualified() {
|
||||||
|
assertEquals("data->>'SomethingCool'",
|
||||||
|
Field.greaterOrEqual("SomethingCool", 18).path(Dialect.SQLITE, FieldFormat.SQL), "Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for simple qualified SQLite field")
|
||||||
|
public void pathSQLiteSimpleQualified() {
|
||||||
|
assertEquals("this.data->>'SomethingElse'",
|
||||||
|
Field.less("SomethingElse", 9).withQualifier("this").path(Dialect.SQLITE, FieldFormat.SQL),
|
||||||
|
"Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for nested unqualified SQLite field")
|
||||||
|
public void pathSQLiteNestedUnqualified() {
|
||||||
|
assertEquals("data->'My'->'Nested'->>'Field'",
|
||||||
|
Field.equal("My.Nested.Field", "howdy").path(Dialect.SQLITE, FieldFormat.SQL), "Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("path generates for nested qualified SQLite field")
|
||||||
|
public void pathSQLiteNestedQualified() {
|
||||||
|
assertEquals("bird.data->'Nest'->>'Away'",
|
||||||
|
Field.equal("Nest.Away", "doc").withQualifier("bird").path(Dialect.SQLITE, FieldFormat.SQL),
|
||||||
|
"Path not correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for exists w/o qualifier (PostgreSQL)")
|
||||||
|
public void toWhereExistsNoQualPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereExistsNoQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereNotExistsNoQualPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereNotExistsNoQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereBetweenNoQualNumericPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereBetweenNoQualAlphaPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereBetweenNoQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereBetweenQualNumericPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereBetweenQualAlphaPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereBetweenQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereAnyNumericPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
assertEquals("(data->>'even')::numeric IN (:nbr_0, :nbr_1, :nbr_2)",
|
||||||
|
Field.any("even", List.of(2, 4, 6), ":nbr").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for IN/any, alphanumeric values (PostgreSQL)")
|
||||||
|
public void toWhereAnyAlphaPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
assertEquals("data->>'test' IN (:city_0, :city_1)",
|
||||||
|
Field.any("test", List.of("Atlanta", "Chicago"), ":city").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for IN/any (SQLite)")
|
||||||
|
public void toWhereAnySQLite() {
|
||||||
|
Configuration.setConnectionString(":sqlite:");
|
||||||
|
assertEquals("data->>'test' IN (:city_0, :city_1)",
|
||||||
|
Field.any("test", List.of("Atlanta", "Chicago"), ":city").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for inArray (PostgreSQL)")
|
||||||
|
public void toWhereInArrayPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
assertEquals("data->'even' ??| ARRAY[:it_0, :it_1, :it_2, :it_3]",
|
||||||
|
Field.inArray("even", "tbl", List.of(2, 4, 6, 8), ":it").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for inArray (SQLite)")
|
||||||
|
public void toWhereInArraySQLite() {
|
||||||
|
Configuration.setConnectionString(":sqlite:");
|
||||||
|
assertEquals("EXISTS (SELECT 1 FROM json_each(tbl.data, '$.test') WHERE value IN (:city_0, :city_1))",
|
||||||
|
Field.inArray("test", "tbl", List.of("Atlanta", "Chicago"), ":city").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("toWhere generates for others w/o qualifier (PostgreSQL)")
|
||||||
|
public void toWhereOtherNoQualPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereOtherNoQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereNoParamWithQualPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereNoParamWithQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":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)")
|
||||||
|
public void toWhereParamWithQualPostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
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)")
|
||||||
|
public void toWhereParamWithQualSQLite() {
|
||||||
|
Configuration.setConnectionString(":sqlite:");
|
||||||
|
assertEquals("q.data->>'le_field' <= :it",
|
||||||
|
Field.lessOrEqual("le_field", 18, ":it").withQualifier("q").toWhere(),
|
||||||
|
"Field WHERE clause not generated correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~~ STATIC TESTS ~~~
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("equal constructs a field w/o parameter name")
|
||||||
|
public void equalCtor() {
|
||||||
|
Field<Integer> field = Field.equal("Test", 14);
|
||||||
|
assertEquals("Test", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(14, field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("equal constructs a field w/ parameter name")
|
||||||
|
public void equalParameterCtor() {
|
||||||
|
Field<Integer> field = Field.equal("Test", 14, ":w");
|
||||||
|
assertEquals("Test", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(14, field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":w", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("greater constructs a field w/o parameter name")
|
||||||
|
public void greaterCtor() {
|
||||||
|
Field<String> field = Field.greater("Great", "night");
|
||||||
|
assertEquals("Great", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.GREATER, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("night", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("greater constructs a field w/ parameter name")
|
||||||
|
public void greaterParameterCtor() {
|
||||||
|
Field<String> field = Field.greater("Great", "night", ":yeah");
|
||||||
|
assertEquals("Great", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.GREATER, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("night", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":yeah", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("greaterOrEqual constructs a field w/o parameter name")
|
||||||
|
public void greaterOrEqualCtor() {
|
||||||
|
Field<Long> field = Field.greaterOrEqual("Nice", 88L);
|
||||||
|
assertEquals("Nice", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.GREATER_OR_EQUAL, field.getComparison().getOp(),
|
||||||
|
"Field comparison operation not filled correctly");
|
||||||
|
assertEquals(88L, field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("greaterOrEqual constructs a field w/ parameter name")
|
||||||
|
public void greaterOrEqualParameterCtor() {
|
||||||
|
Field<Long> field = Field.greaterOrEqual("Nice", 88L, ":nice");
|
||||||
|
assertEquals("Nice", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.GREATER_OR_EQUAL, field.getComparison().getOp(),
|
||||||
|
"Field comparison operation not filled correctly");
|
||||||
|
assertEquals(88L, field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":nice", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("less constructs a field w/o parameter name")
|
||||||
|
public void lessCtor() {
|
||||||
|
Field<String> field = Field.less("Lesser", "seven");
|
||||||
|
assertEquals("Lesser", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.LESS, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("seven", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("less constructs a field w/ parameter name")
|
||||||
|
public void lessParameterCtor() {
|
||||||
|
Field<String> field = Field.less("Lesser", "seven", ":max");
|
||||||
|
assertEquals("Lesser", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.LESS, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("seven", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":max", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("lessOrEqual constructs a field w/o parameter name")
|
||||||
|
public void lessOrEqualCtor() {
|
||||||
|
Field<String> field = Field.lessOrEqual("Nobody", "KNOWS");
|
||||||
|
assertEquals("Nobody", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.LESS_OR_EQUAL, field.getComparison().getOp(),
|
||||||
|
"Field comparison operation not filled correctly");
|
||||||
|
assertEquals("KNOWS", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("lessOrEqual constructs a field w/ parameter name")
|
||||||
|
public void lessOrEqualParameterCtor() {
|
||||||
|
Field<String> field = Field.lessOrEqual("Nobody", "KNOWS", ":nope");
|
||||||
|
assertEquals("Nobody", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.LESS_OR_EQUAL, field.getComparison().getOp(),
|
||||||
|
"Field comparison operation not filled correctly");
|
||||||
|
assertEquals("KNOWS", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":nope", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("notEqual constructs a field w/o parameter name")
|
||||||
|
public void notEqualCtor() {
|
||||||
|
Field<String> field = Field.notEqual("Park", "here");
|
||||||
|
assertEquals("Park", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.NOT_EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("here", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("notEqual constructs a field w/ parameter name")
|
||||||
|
public void notEqualParameterCtor() {
|
||||||
|
Field<String> field = Field.notEqual("Park", "here", ":now");
|
||||||
|
assertEquals("Park", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.NOT_EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("here", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertEquals(":now", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("between constructs a field w/o parameter name")
|
||||||
|
public void betweenCtor() {
|
||||||
|
Field<Pair<Integer, Integer>> field = Field.between("Age", 18, 49);
|
||||||
|
assertEquals("Age", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.BETWEEN, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(18, field.getComparison().getValue().getFirst(),
|
||||||
|
"Field comparison min value not filled correctly");
|
||||||
|
assertEquals(49, field.getComparison().getValue().getSecond(),
|
||||||
|
"Field comparison max value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("between constructs a field w/ parameter name")
|
||||||
|
public void betweenParameterCtor() {
|
||||||
|
Field<Pair<Integer, Integer>> field = Field.between("Age", 18, 49, ":limit");
|
||||||
|
assertEquals("Age", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.BETWEEN, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(18, field.getComparison().getValue().getFirst(),
|
||||||
|
"Field comparison min value not filled correctly");
|
||||||
|
assertEquals(49, field.getComparison().getValue().getSecond(),
|
||||||
|
"Field comparison max value not filled correctly");
|
||||||
|
assertEquals(":limit", field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("any constructs a field w/o parameter name")
|
||||||
|
public void anyCtor() {
|
||||||
|
Field<Collection<Integer>> field = Field.any("Here", List.of(8, 16, 32));
|
||||||
|
assertEquals("Here", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.IN, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(List.of(8, 16, 32), field.getComparison().getValue(),
|
||||||
|
"Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("any constructs a field w/ parameter name")
|
||||||
|
public void anyParameterCtor() {
|
||||||
|
Field<Collection<Integer>> field = Field.any("Here", List.of(8, 16, 32), ":list");
|
||||||
|
assertEquals("Here", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.IN, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals(List.of(8, 16, 32), field.getComparison().getValue(),
|
||||||
|
"Field comparison value not filled correctly");
|
||||||
|
assertEquals(":list", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("inArray constructs a field w/o parameter name")
|
||||||
|
public void inArrayCtor() {
|
||||||
|
Field<Pair<String, Collection<String>>> field = Field.inArray("ArrayField", "table", List.of("z"));
|
||||||
|
assertEquals("ArrayField", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.IN_ARRAY, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("table", field.getComparison().getValue().getFirst(),
|
||||||
|
"Field comparison table not filled correctly");
|
||||||
|
assertEquals(List.of("z"), field.getComparison().getValue().getSecond(),
|
||||||
|
"Field comparison values not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("inArray constructs a field w/ parameter name")
|
||||||
|
public void inArrayParameterCtor() {
|
||||||
|
Field<Pair<String, Collection<String>>> field = Field.inArray("ArrayField", "table", List.of("z"), ":a");
|
||||||
|
assertEquals("ArrayField", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.IN_ARRAY, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("table", field.getComparison().getValue().getFirst(),
|
||||||
|
"Field comparison table not filled correctly");
|
||||||
|
assertEquals(List.of("z"), field.getComparison().getValue().getSecond(),
|
||||||
|
"Field comparison values not filled correctly");
|
||||||
|
assertEquals(":a", field.getParameterName(), "Field parameter name not filled correctly");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("exists constructs a field")
|
||||||
|
public void existsCtor() {
|
||||||
|
Field<String> field = Field.exists("Groovy");
|
||||||
|
assertEquals("Groovy", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.EXISTS, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("notExists constructs a field")
|
||||||
|
public void notExistsCtor() {
|
||||||
|
Field<String> field = Field.notExists("Groovy");
|
||||||
|
assertEquals("Groovy", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.NOT_EXISTS, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("named constructs a field")
|
||||||
|
public void namedCtor() {
|
||||||
|
Field<String> field = Field.named("Tacos");
|
||||||
|
assertEquals("Tacos", field.getName(), "Field name not filled correctly");
|
||||||
|
assertEquals(Op.EQUAL, field.getComparison().getOp(), "Field comparison operation not filled correctly");
|
||||||
|
assertEquals("", field.getComparison().getValue(), "Field comparison value not filled correctly");
|
||||||
|
assertNull(field.getParameterName(), "The parameter name should have been null");
|
||||||
|
assertNull(field.getQualifier(), "The qualifier should have been null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("static constructors fail for invalid parameter name")
|
||||||
|
public void staticCtorsFailOnParamName() {
|
||||||
|
assertThrows(DocumentException.class, () -> Field.equal("a", "b", "that ain't it, Jack..."));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a simple PostgreSQL SQL name")
|
||||||
|
public void nameToPathPostgresSimpleSQL() {
|
||||||
|
assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.SQL),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a simple SQLite SQL name")
|
||||||
|
public void nameToPathSQLiteSimpleSQL() {
|
||||||
|
assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.SQL),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a nested PostgreSQL SQL name")
|
||||||
|
public void nameToPathPostgresNestedSQL() {
|
||||||
|
assertEquals("data#>>'{A,Long,Path,to,the,Property}'",
|
||||||
|
Field.nameToPath("A.Long.Path.to.the.Property", Dialect.POSTGRESQL, FieldFormat.SQL),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a nested SQLite SQL name")
|
||||||
|
public void nameToPathSQLiteNestedSQL() {
|
||||||
|
assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->>'Property'",
|
||||||
|
Field.nameToPath("A.Long.Path.to.the.Property", Dialect.SQLITE, FieldFormat.SQL),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a simple PostgreSQL JSON name")
|
||||||
|
public void nameToPathPostgresSimpleJSON() {
|
||||||
|
assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.JSON),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a simple SQLite JSON name")
|
||||||
|
public void nameToPathSQLiteSimpleJSON() {
|
||||||
|
assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.JSON),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a nested PostgreSQL JSON name")
|
||||||
|
public void nameToPathPostgresNestedJSON() {
|
||||||
|
assertEquals("data#>'{A,Long,Path,to,the,Property}'",
|
||||||
|
Field.nameToPath("A.Long.Path.to.the.Property", Dialect.POSTGRESQL, FieldFormat.JSON),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameToPath creates a nested SQLite JSON name")
|
||||||
|
public void nameToPathSQLiteNestedJSON() {
|
||||||
|
assertEquals("data->'A'->'Long'->'Path'->'to'->'the'->'Property'",
|
||||||
|
Field.nameToPath("A.Long.Path.to.the.Property", Dialect.SQLITE, FieldFormat.JSON),
|
||||||
|
"Path not constructed correctly");
|
||||||
|
}
|
||||||
|
}
|
80
src/test/java/solutions/bitbadger/documents/java/OpTest.java
Normal file
80
src/test/java/solutions/bitbadger/documents/java/OpTest.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.Op;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `Op` enum
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | Op")
|
||||||
|
final public class OpTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EQUAL uses proper SQL")
|
||||||
|
public void equalSQL() {
|
||||||
|
assertEquals("=", Op.EQUAL.getSql(), "The SQL for equal is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GREATER uses proper SQL")
|
||||||
|
public void greaterSQL() {
|
||||||
|
assertEquals(">", Op.GREATER.getSql(), "The SQL for greater is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("GREATER_OR_EQUAL uses proper SQL")
|
||||||
|
public void greaterOrEqualSQL() {
|
||||||
|
assertEquals(">=", Op.GREATER_OR_EQUAL.getSql(), "The SQL for greater-or-equal is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("LESS uses proper SQL")
|
||||||
|
public void lessSQL() {
|
||||||
|
assertEquals("<", Op.LESS.getSql(), "The SQL for less is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("LESS_OR_EQUAL uses proper SQL")
|
||||||
|
public void lessOrEqualSQL() {
|
||||||
|
assertEquals("<=", Op.LESS_OR_EQUAL.getSql(), "The SQL for less-or-equal is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("NOT_EQUAL uses proper SQL")
|
||||||
|
public void notEqualSQL() {
|
||||||
|
assertEquals("<>", Op.NOT_EQUAL.getSql(), "The SQL for not-equal is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("BETWEEN uses proper SQL")
|
||||||
|
public void betweenSQL() {
|
||||||
|
assertEquals("BETWEEN", Op.BETWEEN.getSql(), "The SQL for between is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("IN uses proper SQL")
|
||||||
|
public void inSQL() {
|
||||||
|
assertEquals("IN", Op.IN.getSql(), "The SQL for in is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("IN_ARRAY uses proper SQL")
|
||||||
|
public void inArraySQL() {
|
||||||
|
assertEquals("??|", Op.IN_ARRAY.getSql(), "The SQL for in-array is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("EXISTS uses proper SQL")
|
||||||
|
public void existsSQL() {
|
||||||
|
assertEquals("IS NOT NULL", Op.EXISTS.getSql(), "The SQL for exists is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("NOT_EXISTS uses proper SQL")
|
||||||
|
public void notExistsSQL() {
|
||||||
|
assertEquals("IS NULL", Op.NOT_EXISTS.getSql(), "The SQL for not-exists is incorrect");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.ParameterName;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `ParameterName` class
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | ParameterName")
|
||||||
|
final public class ParameterNameTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("derive works when given existing names")
|
||||||
|
public void withExisting() {
|
||||||
|
ParameterName names = new ParameterName();
|
||||||
|
assertEquals(":taco", names.derive(":taco"), "Name should have been :taco");
|
||||||
|
assertEquals(":field0", names.derive(null), "Counter should not have advanced for named field");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("derive works when given all anonymous fields")
|
||||||
|
public void allAnonymous() {
|
||||||
|
ParameterName names = new ParameterName();
|
||||||
|
assertEquals(":field0", names.derive(null), "Anonymous field name should have been returned");
|
||||||
|
assertEquals(":field1", names.derive(null), "Counter should have advanced from previous call");
|
||||||
|
assertEquals(":field2", names.derive(null), "Counter should have advanced from previous call");
|
||||||
|
assertEquals(":field3", names.derive(null), "Counter should have advanced from previous call");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.DocumentException;
|
||||||
|
import solutions.bitbadger.documents.Parameter;
|
||||||
|
import solutions.bitbadger.documents.ParameterType;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `Parameter` class
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | Parameter")
|
||||||
|
final public class ParameterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Construction with colon-prefixed name")
|
||||||
|
public void ctorWithColon() {
|
||||||
|
Parameter<String> p = new Parameter<>(":test", ParameterType.STRING, "ABC");
|
||||||
|
assertEquals(":test", p.getName(), "Parameter name was incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, p.getType(), "Parameter type was incorrect");
|
||||||
|
assertEquals("ABC", p.getValue(), "Parameter value was incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Construction with at-sign-prefixed name")
|
||||||
|
public void ctorWithAtSign() {
|
||||||
|
Parameter<String> p = new Parameter<>("@yo", ParameterType.NUMBER, null);
|
||||||
|
assertEquals("@yo", p.getName(), "Parameter name was incorrect");
|
||||||
|
assertEquals(ParameterType.NUMBER, p.getType(), "Parameter type was incorrect");
|
||||||
|
assertNull(p.getValue(), "Parameter value was incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Construction fails with incorrect prefix")
|
||||||
|
public void ctorFailsForPrefix() {
|
||||||
|
assertThrows(DocumentException.class, () -> new Parameter<>("it", ParameterType.JSON, ""));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
package solutions.bitbadger.documents.java;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import solutions.bitbadger.documents.*;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `Parameters` object
|
||||||
|
*/
|
||||||
|
@DisplayName("Java | Parameters")
|
||||||
|
final public class ParametersTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the dialect
|
||||||
|
*/
|
||||||
|
@AfterEach
|
||||||
|
public void cleanUp() {
|
||||||
|
Configuration.setConnectionString(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameFields works with no changes")
|
||||||
|
public void nameFieldsNoChange() {
|
||||||
|
List<Field<?>> fields = List.of(Field.equal("a", "", ":test"), Field.exists("q"), Field.equal("b", "", ":me"));
|
||||||
|
Field<?>[] named = Parameters.nameFields(fields).toArray(new Field<?>[] { });
|
||||||
|
assertEquals(fields.size(), named.length, "There should have been 3 fields in the list");
|
||||||
|
assertSame(fields.get(0), named[0], "The first field should be the same");
|
||||||
|
assertSame(fields.get(1), named[1], "The second field should be the same");
|
||||||
|
assertSame(fields.get(2), named[2], "The third field should be the same");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("nameFields works when changing fields")
|
||||||
|
public void nameFieldsChange() {
|
||||||
|
List<Field<?>> fields = List.of(
|
||||||
|
Field.equal("a", ""), Field.equal("e", "", ":hi"), Field.equal("b", ""), Field.notExists("z"));
|
||||||
|
Field<?>[] named = Parameters.nameFields(fields).toArray(new Field<?>[] { });
|
||||||
|
assertEquals(fields.size(), named.length, "There should have been 4 fields in the list");
|
||||||
|
assertNotSame(fields.get(0), named[0], "The first field should not be the same");
|
||||||
|
assertEquals(":field0", named[0].getParameterName(), "First parameter name incorrect");
|
||||||
|
assertSame(fields.get(1), named[1], "The second field should be the same");
|
||||||
|
assertNotSame(fields.get(2), named[2], "The third field should not be the same");
|
||||||
|
assertEquals(":field1", named[2].getParameterName(), "Third parameter name incorrect");
|
||||||
|
assertSame(fields.get(3), named[3], "The fourth field should be the same");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("replaceNamesInQuery replaces successfully")
|
||||||
|
public void replaceNamesInQuery() {
|
||||||
|
List<Parameter<?>> parameters = List.of(new Parameter<>(":data", ParameterType.JSON, "{}"),
|
||||||
|
new Parameter<>(":data_ext", ParameterType.STRING, ""));
|
||||||
|
String query =
|
||||||
|
"SELECT data, data_ext FROM tbl WHERE data = :data AND data_ext = :data_ext AND more_data = :data";
|
||||||
|
assertEquals("SELECT data, data_ext FROM tbl WHERE data = ? AND data_ext = ? AND more_data = ?",
|
||||||
|
Parameters.replaceNamesInQuery(query, parameters), "Parameters not replaced correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fieldNames generates a single parameter (PostgreSQL)")
|
||||||
|
public void fieldNamesSinglePostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
Parameter<?>[] nameParams = Parameters.fieldNames(List.of("test")).toArray(new Parameter<?>[] { });
|
||||||
|
assertEquals(1, nameParams.length, "There should be one name parameter");
|
||||||
|
assertEquals(":name", nameParams[0].getName(), "The parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect");
|
||||||
|
assertEquals("{test}", nameParams[0].getValue(), "The parameter value is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fieldNames generates multiple parameters (PostgreSQL)")
|
||||||
|
public void fieldNamesMultiplePostgres() {
|
||||||
|
Configuration.setConnectionString(":postgresql:");
|
||||||
|
Parameter<?>[] nameParams = Parameters.fieldNames(List.of("test", "this", "today"))
|
||||||
|
.toArray(new Parameter<?>[] { });
|
||||||
|
assertEquals(1, nameParams.length, "There should be one name parameter");
|
||||||
|
assertEquals(":name", nameParams[0].getName(), "The parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect");
|
||||||
|
assertEquals("{test,this,today}", nameParams[0].getValue(), "The parameter value is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fieldNames generates a single parameter (SQLite)")
|
||||||
|
public void fieldNamesSingleSQLite() {
|
||||||
|
Configuration.setConnectionString(":sqlite:");
|
||||||
|
Parameter<?>[] nameParams = Parameters.fieldNames(List.of("test")).toArray(new Parameter<?>[] { });
|
||||||
|
assertEquals(1, nameParams.length, "There should be one name parameter");
|
||||||
|
assertEquals(":name0", nameParams[0].getName(), "The parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[0].getType(), "The parameter type is incorrect");
|
||||||
|
assertEquals("test", nameParams[0].getValue(), "The parameter value is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fieldNames generates multiple parameters (SQLite)")
|
||||||
|
public void fieldNamesMultipleSQLite() {
|
||||||
|
Configuration.setConnectionString(":sqlite:");
|
||||||
|
Parameter<?>[] nameParams = Parameters.fieldNames(List.of("test", "this", "today"))
|
||||||
|
.toArray(new Parameter<?>[] { });
|
||||||
|
assertEquals(3, nameParams.length, "There should be one name parameter");
|
||||||
|
assertEquals(":name0", nameParams[0].getName(), "The first parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[0].getType(), "The first parameter type is incorrect");
|
||||||
|
assertEquals("test", nameParams[0].getValue(), "The first parameter value is incorrect");
|
||||||
|
assertEquals(":name1", nameParams[1].getName(), "The second parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[1].getType(), "The second parameter type is incorrect");
|
||||||
|
assertEquals("this", nameParams[1].getValue(), "The second parameter value is incorrect");
|
||||||
|
assertEquals(":name2", nameParams[2].getName(), "The third parameter name is incorrect");
|
||||||
|
assertEquals(ParameterType.STRING, nameParams[2].getType(), "The third parameter type is incorrect");
|
||||||
|
assertEquals("today", nameParams[2].getValue(), "The third parameter value is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("fieldNames fails if dialect not set")
|
||||||
|
public void fieldNamesFails() {
|
||||||
|
assertThrows(DocumentException.class, () -> Parameters.fieldNames(List.of()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package solutions.bitbadger.documents.java.testDocs;
|
||||||
|
|
||||||
|
public class ByteIdClass {
|
||||||
|
|
||||||
|
private byte id;
|
||||||
|
|
||||||
|
public byte getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(byte id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteIdClass(byte id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package solutions.bitbadger.documents.java.testDocs;
|
||||||
|
|
||||||
|
public class IntIdClass {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntIdClass(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package solutions.bitbadger.documents.java.testDocs;
|
||||||
|
|
||||||
|
public class LongIdClass {
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongIdClass(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package solutions.bitbadger.documents.java.testDocs;
|
||||||
|
|
||||||
|
public class ShortIdClass {
|
||||||
|
|
||||||
|
private short id;
|
||||||
|
|
||||||
|
public short getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(short id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShortIdClass(short id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package solutions.bitbadger.documents.java.testDocs;
|
||||||
|
|
||||||
|
public class StringIdClass {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringIdClass(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ import kotlin.test.assertTrue
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `AutoId` enum
|
* Unit tests for the `AutoId` enum
|
||||||
*/
|
*/
|
||||||
@DisplayName("AutoId")
|
@DisplayName("Kotlin | AutoId")
|
||||||
class AutoIdTest {
|
class AutoIdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -66,8 +66,10 @@ class AutoIdTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0")
|
@DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0")
|
||||||
fun needsAutoIdFalseForByteWithNonZero() =
|
fun needsAutoIdFalseForByteWithNonZero() =
|
||||||
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(77), "id"),
|
assertFalse(
|
||||||
"Number Auto ID with 77 should return false")
|
AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(77), "id"),
|
||||||
|
"Number Auto ID with 77 should return false"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns true for Number strategy and short ID of 0")
|
@DisplayName("needsAutoId returns true for Number strategy and short ID of 0")
|
||||||
@ -77,8 +79,10 @@ class AutoIdTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns false for Number strategy and short ID of non-0")
|
@DisplayName("needsAutoId returns false for Number strategy and short ID of non-0")
|
||||||
fun needsAutoIdFalseForShortWithNonZero() =
|
fun needsAutoIdFalseForShortWithNonZero() =
|
||||||
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(31), "id"),
|
assertFalse(
|
||||||
"Number Auto ID with 31 should return false")
|
AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(31), "id"),
|
||||||
|
"Number Auto ID with 31 should return false"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns true for Number strategy and int ID of 0")
|
@DisplayName("needsAutoId returns true for Number strategy and int ID of 0")
|
||||||
@ -98,7 +102,10 @@ class AutoIdTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns false for Number strategy and long ID of non-0")
|
@DisplayName("needsAutoId returns false for Number strategy and long ID of non-0")
|
||||||
fun needsAutoIdFalseForLongWithNonZero() =
|
fun needsAutoIdFalseForLongWithNonZero() =
|
||||||
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, IntIdClass(2), "id"), "Number Auto ID with 2 should return false")
|
assertFalse(
|
||||||
|
AutoId.needsAutoId(AutoId.NUMBER, LongIdClass(2), "id"),
|
||||||
|
"Number Auto ID with 2 should return false"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId fails for Number strategy and non-number ID")
|
@DisplayName("needsAutoId fails for Number strategy and non-number ID")
|
||||||
@ -109,14 +116,18 @@ class AutoIdTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns true for UUID strategy and blank ID")
|
@DisplayName("needsAutoId returns true for UUID strategy and blank ID")
|
||||||
fun needsAutoIdTrueForUUIDWithBlank() =
|
fun needsAutoIdTrueForUUIDWithBlank() =
|
||||||
assertTrue(AutoId.needsAutoId(AutoId.UUID, StringIdClass(""), "id"),
|
assertTrue(
|
||||||
"UUID Auto ID with blank should return true")
|
AutoId.needsAutoId(AutoId.UUID, StringIdClass(""), "id"),
|
||||||
|
"UUID Auto ID with blank should return true"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns false for UUID strategy and non-blank ID")
|
@DisplayName("needsAutoId returns false for UUID strategy and non-blank ID")
|
||||||
fun needsAutoIdFalseForUUIDNotBlank() =
|
fun needsAutoIdFalseForUUIDNotBlank() =
|
||||||
assertFalse(AutoId.needsAutoId(AutoId.UUID, StringIdClass("howdy"), "id"),
|
assertFalse(
|
||||||
"UUID Auto ID with non-blank should return false")
|
AutoId.needsAutoId(AutoId.UUID, StringIdClass("howdy"), "id"),
|
||||||
|
"UUID Auto ID with non-blank should return false"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId fails for UUID strategy and non-string ID")
|
@DisplayName("needsAutoId fails for UUID strategy and non-string ID")
|
||||||
@ -127,14 +138,18 @@ class AutoIdTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns true for Random String strategy and blank ID")
|
@DisplayName("needsAutoId returns true for Random String strategy and blank ID")
|
||||||
fun needsAutoIdTrueForRandomWithBlank() =
|
fun needsAutoIdTrueForRandomWithBlank() =
|
||||||
assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass(""), "id"),
|
assertTrue(
|
||||||
"Random String Auto ID with blank should return true")
|
AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass(""), "id"),
|
||||||
|
"Random String Auto ID with blank should return true"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId returns false for Random String strategy and non-blank ID")
|
@DisplayName("needsAutoId returns false for Random String strategy and non-blank ID")
|
||||||
fun needsAutoIdFalseForRandomNotBlank() =
|
fun needsAutoIdFalseForRandomNotBlank() =
|
||||||
assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass("full"), "id"),
|
assertFalse(
|
||||||
"Random String Auto ID with non-blank should return false")
|
AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass("full"), "id"),
|
||||||
|
"Random String Auto ID with non-blank should return false"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("needsAutoId fails for Random String strategy and non-string ID")
|
@DisplayName("needsAutoId fails for Random String strategy and non-string ID")
|
||||||
|
@ -10,7 +10,7 @@ import kotlin.test.assertTrue
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `Configuration` object
|
* Unit tests for the `Configuration` object
|
||||||
*/
|
*/
|
||||||
@DisplayName("Configuration")
|
@DisplayName("Kotlin | Configuration")
|
||||||
class ConfigurationTest {
|
class ConfigurationTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `DocumentIndex` enum
|
* Unit tests for the `DocumentIndex` enum
|
||||||
*/
|
*/
|
||||||
@DisplayName("Op")
|
@DisplayName("Kotlin | DocumentIndex")
|
||||||
class DocumentIndexTest {
|
class DocumentIndexTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `FieldMatch` enum
|
* Unit tests for the `FieldMatch` enum
|
||||||
*/
|
*/
|
||||||
@DisplayName("FieldMatch")
|
@DisplayName("Kotlin | FieldMatch")
|
||||||
class FieldMatchTest {
|
class FieldMatchTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -11,7 +11,7 @@ import kotlin.test.assertNull
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `Field` class
|
* Unit tests for the `Field` class
|
||||||
*/
|
*/
|
||||||
@DisplayName("Field")
|
@DisplayName("Kotlin | Field")
|
||||||
class FieldTest {
|
class FieldTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `Op` enum
|
* Unit tests for the `Op` enum
|
||||||
*/
|
*/
|
||||||
@DisplayName("Op")
|
@DisplayName("Kotlin | Op")
|
||||||
class OpTest {
|
class OpTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `ParameterName` class
|
* Unit tests for the `ParameterName` class
|
||||||
*/
|
*/
|
||||||
@DisplayName("ParameterName")
|
@DisplayName("Kotlin | ParameterName")
|
||||||
class ParameterNameTest {
|
class ParameterNameTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -9,7 +9,7 @@ import kotlin.test.assertNull
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `Parameter` class
|
* Unit tests for the `Parameter` class
|
||||||
*/
|
*/
|
||||||
@DisplayName("Parameter")
|
@DisplayName("Kotlin | Parameter")
|
||||||
class ParameterTest {
|
class ParameterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -11,7 +11,7 @@ import kotlin.test.assertSame
|
|||||||
/**
|
/**
|
||||||
* Unit tests for the `Parameters` object
|
* Unit tests for the `Parameters` object
|
||||||
*/
|
*/
|
||||||
@DisplayName("Parameters")
|
@DisplayName("Kotlin | Parameters")
|
||||||
class ParametersTest {
|
class ParametersTest {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user