Initial Development #1
@ -17,7 +17,7 @@ object Count {
|
|||||||
JsonDocument.load(db)
|
JsonDocument.load(db)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
3L,
|
3L,
|
||||||
db.conn.countByFields(TEST_TABLE, listOf(Field.between("num_value", 10, 20))),
|
db.conn.countByFields(TEST_TABLE, listOf(Field.between("numValue", 10, 20))),
|
||||||
"There should have been 3 matching documents"
|
"There should have been 3 matching documents"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -53,7 +53,7 @@ object Count {
|
|||||||
JsonDocument.load(db)
|
JsonDocument.load(db)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
2L,
|
2L,
|
||||||
db.conn.countByJsonPath(TEST_TABLE, "$.num_value ? (@ < 5)"),
|
db.conn.countByJsonPath(TEST_TABLE, "$.numValue ? (@ < 5)"),
|
||||||
"There should have been 2 matching documents"
|
"There should have been 2 matching documents"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ object Count {
|
|||||||
JsonDocument.load(db)
|
JsonDocument.load(db)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
0L,
|
0L,
|
||||||
db.conn.countByJsonPath(TEST_TABLE, "$.num_value ? (@ > 100)"),
|
db.conn.countByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)"),
|
||||||
"There should have been no matching documents"
|
"There should have been no matching documents"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,43 @@
|
|||||||
package solutions.bitbadger.documents
|
package solutions.bitbadger.documents
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information required to generate a JSON field comparison
|
||||||
|
*/
|
||||||
interface Comparison<T> {
|
interface Comparison<T> {
|
||||||
|
|
||||||
|
/** The operation for the field comparison */
|
||||||
val op: Op
|
val op: Op
|
||||||
|
|
||||||
val isNumeric: Boolean
|
/** The value against which the comparison will be made */
|
||||||
|
|
||||||
val value: T
|
val value: T
|
||||||
|
|
||||||
|
/** Whether the value should be considered numeric */
|
||||||
|
val isNumeric: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A single-value comparison against a field in a JSON document
|
* Function to determine if a value is numeric
|
||||||
*
|
*
|
||||||
* @property op The operation for the field comparison
|
* @param it The value in question
|
||||||
* @property value The value against which the comparison will be made
|
* @return True if it is a numeric type, false if not
|
||||||
*/
|
*/
|
||||||
class SingleComparison<T>(override val op: Op, override val value: T) : Comparison<T> {
|
private fun <T> isNumeric(it: T) =
|
||||||
|
it is Byte || it is Short || it is Int || it is Long
|
||||||
|
|
||||||
/** Is the value for this comparison a numeric value? */
|
/**
|
||||||
override val isNumeric: Boolean
|
* A single-value comparison against a field in a JSON document
|
||||||
get() = value.let { it is Byte || it is Short || it is Int || it is Long }
|
*/
|
||||||
|
class ComparisonSingle<T>(override val op: Op, override val value: T) : Comparison<T> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
when (op) {
|
||||||
|
Op.BETWEEN, Op.IN, Op.IN_ARRAY ->
|
||||||
|
throw DocumentException("Cannot use single comparison for multiple values")
|
||||||
|
else -> { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val isNumeric = isNumeric(value)
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"$op $value"
|
"$op $value"
|
||||||
@ -28,27 +46,23 @@ class SingleComparison<T>(override val op: Op, override val value: T) : Comparis
|
|||||||
/**
|
/**
|
||||||
* A range comparison against a field in a JSON document
|
* A range comparison against a field in a JSON document
|
||||||
*/
|
*/
|
||||||
class BetweenComparison<T>(override val op: Op = Op.BETWEEN, override val value: Pair<T, T>) : Comparison<Pair<T, T>> {
|
class ComparisonBetween<T>(override val value: Pair<T, T>) : Comparison<Pair<T, T>> {
|
||||||
|
override val op = Op.BETWEEN
|
||||||
override val isNumeric: Boolean
|
override val isNumeric = isNumeric(value.first)
|
||||||
get() = value.first.let { it is Byte || it is Short || it is Int || it is Long }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A check within a collection of values
|
* A check within a collection of values
|
||||||
*/
|
*/
|
||||||
class InComparison<T>(override val op: Op = Op.IN, override val value: Collection<T>) : Comparison<Collection<T>> {
|
class ComparisonIn<T>(override val value: Collection<T>) : Comparison<Collection<T>> {
|
||||||
|
override val op = Op.IN
|
||||||
override val isNumeric: Boolean
|
override val isNumeric = !value.isEmpty() && isNumeric(value.elementAt(0))
|
||||||
get() = !value.isEmpty() && value.elementAt(0).let { it is Byte || it is Short || it is Int || it is Long }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A check within a collection of values
|
* A check within a collection of values against an array in a document
|
||||||
*/
|
*/
|
||||||
class InArrayComparison<T>(override val op: Op = Op.IN_ARRAY, override val value: Pair<String, Collection<T>>) : Comparison<Pair<String, Collection<T>>> {
|
class ComparisonInArray<T>(override val value: Pair<String, Collection<T>>) : Comparison<Pair<String, Collection<T>>> {
|
||||||
|
override val op = Op.IN_ARRAY
|
||||||
override val isNumeric: Boolean
|
override val isNumeric = false
|
||||||
get() = !value.second.isEmpty() && value.second.elementAt(0)
|
|
||||||
.let { it is Byte || it is Short || it is Int || it is Long }
|
|
||||||
}
|
}
|
||||||
|
@ -101,18 +101,18 @@ class Field<T> private constructor(
|
|||||||
fun appendParameter(existing: MutableCollection<Parameter<*>>): MutableCollection<Parameter<*>> {
|
fun appendParameter(existing: MutableCollection<Parameter<*>>): MutableCollection<Parameter<*>> {
|
||||||
val typ = if (comparison.isNumeric) ParameterType.NUMBER else ParameterType.STRING
|
val typ = if (comparison.isNumeric) ParameterType.NUMBER else ParameterType.STRING
|
||||||
when (comparison) {
|
when (comparison) {
|
||||||
is BetweenComparison<*> -> {
|
is ComparisonBetween<*> -> {
|
||||||
existing.add(Parameter("${parameterName}min", typ, comparison.value.first))
|
existing.add(Parameter("${parameterName}min", typ, comparison.value.first))
|
||||||
existing.add(Parameter("${parameterName}max", typ, comparison.value.second))
|
existing.add(Parameter("${parameterName}max", typ, comparison.value.second))
|
||||||
}
|
}
|
||||||
|
|
||||||
is InComparison<*> -> {
|
is ComparisonIn<*> -> {
|
||||||
comparison.value.forEachIndexed { index, item ->
|
comparison.value.forEachIndexed { index, item ->
|
||||||
existing.add(Parameter("${parameterName}_$index", typ, item))
|
existing.add(Parameter("${parameterName}_$index", typ, item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is InArrayComparison<*> -> {
|
is ComparisonInArray<*> -> {
|
||||||
val mkString = Configuration.dialect("append parameters for InArray") == Dialect.POSTGRESQL
|
val mkString = Configuration.dialect("append parameters for InArray") == Dialect.POSTGRESQL
|
||||||
// TODO: I think this is actually Pair<String, Collection<*>>
|
// TODO: I think this is actually Pair<String, Collection<*>>
|
||||||
comparison.value.second.forEachIndexed { index, item ->
|
comparison.value.second.forEachIndexed { index, item ->
|
||||||
@ -147,7 +147,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> equal(name: String, value: T, paramName: String? = null) =
|
fun <T> equal(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.EQUAL, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field greater-than comparison
|
* Create a field greater-than comparison
|
||||||
@ -158,7 +158,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> greater(name: String, value: T, paramName: String? = null) =
|
fun <T> greater(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.GREATER, value), paramName)
|
Field(name, ComparisonSingle(Op.GREATER, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field greater-than-or-equal-to comparison
|
* Create a field greater-than-or-equal-to comparison
|
||||||
@ -169,7 +169,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> greaterOrEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> greaterOrEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.GREATER_OR_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.GREATER_OR_EQUAL, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field less-than comparison
|
* Create a field less-than comparison
|
||||||
@ -180,7 +180,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> less(name: String, value: T, paramName: String? = null) =
|
fun <T> less(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.LESS, value), paramName)
|
Field(name, ComparisonSingle(Op.LESS, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field less-than-or-equal-to comparison
|
* Create a field less-than-or-equal-to comparison
|
||||||
@ -191,7 +191,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> lessOrEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> lessOrEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.LESS_OR_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.LESS_OR_EQUAL, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field inequality comparison
|
* Create a field inequality comparison
|
||||||
@ -202,7 +202,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> notEqual(name: String, value: T, paramName: String? = null) =
|
fun <T> notEqual(name: String, value: T, paramName: String? = null) =
|
||||||
Field(name, SingleComparison(Op.NOT_EQUAL, value), paramName)
|
Field(name, ComparisonSingle(Op.NOT_EQUAL, value), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field range comparison
|
* Create a field range comparison
|
||||||
@ -214,7 +214,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
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, BetweenComparison(value = Pair(minValue, maxValue)), paramName)
|
Field(name, ComparisonBetween(Pair(minValue, maxValue)), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field where any values match (SQL `IN`)
|
* Create a field where any values match (SQL `IN`)
|
||||||
@ -225,7 +225,7 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
fun <T> any(name: String, values: Collection<T>, paramName: String? = null) =
|
fun <T> any(name: String, values: Collection<T>, paramName: String? = null) =
|
||||||
Field(name, InComparison(value = values), paramName)
|
Field(name, ComparisonIn(values), paramName)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a field where values should exist in a document's array
|
* Create a field where values should exist in a document's array
|
||||||
@ -237,16 +237,16 @@ class Field<T> private constructor(
|
|||||||
* @return A `Field` with the given comparison
|
* @return A `Field` with the given comparison
|
||||||
*/
|
*/
|
||||||
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, InArrayComparison(value = Pair(tableName, values)), paramName)
|
Field(name, ComparisonInArray(Pair(tableName, values)), paramName)
|
||||||
|
|
||||||
fun exists(name: String) =
|
fun exists(name: String) =
|
||||||
Field(name, SingleComparison(Op.EXISTS, ""))
|
Field(name, ComparisonSingle(Op.EXISTS, ""))
|
||||||
|
|
||||||
fun notExists(name: String) =
|
fun notExists(name: String) =
|
||||||
Field(name, SingleComparison(Op.NOT_EXISTS, ""))
|
Field(name, ComparisonSingle(Op.NOT_EXISTS, ""))
|
||||||
|
|
||||||
fun named(name: String) =
|
fun named(name: String) =
|
||||||
Field(name, SingleComparison(Op.EQUAL, ""))
|
Field(name, ComparisonSingle(Op.EQUAL, ""))
|
||||||
|
|
||||||
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")
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package solutions.bitbadger.documents
|
package solutions.bitbadger.documents
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement
|
||||||
|
import java.sql.Types
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parameter to use for a query
|
* A parameter to use for a query
|
||||||
*
|
*
|
||||||
@ -8,11 +11,45 @@ package solutions.bitbadger.documents
|
|||||||
* @property value The value of the parameter
|
* @property value The value of the parameter
|
||||||
*/
|
*/
|
||||||
class Parameter<T>(val name: String, val type: ParameterType, val value: T) {
|
class Parameter<T>(val name: String, val type: ParameterType, val value: T) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!name.startsWith(':') && !name.startsWith('@'))
|
if (!name.startsWith(':') && !name.startsWith('@'))
|
||||||
throw DocumentException("Name must start with : or @ ($name)")
|
throw DocumentException("Name must start with : or @ ($name)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bind this parameter to a prepared statement at the given index
|
||||||
|
*
|
||||||
|
* @param stmt The prepared statement to which this parameter should be bound
|
||||||
|
* @param index The index (1-based) to which the parameter should be bound
|
||||||
|
*/
|
||||||
|
fun bind(stmt: PreparedStatement, index: Int) {
|
||||||
|
when (type) {
|
||||||
|
ParameterType.NUMBER -> {
|
||||||
|
when (value) {
|
||||||
|
null -> stmt.setNull(index, Types.NULL)
|
||||||
|
is Byte -> stmt.setByte(index, value)
|
||||||
|
is Short -> stmt.setShort(index, value)
|
||||||
|
is Int -> stmt.setInt(index, value)
|
||||||
|
is Long -> stmt.setLong(index, value)
|
||||||
|
else -> throw DocumentException(
|
||||||
|
"Number parameter must be Byte, Short, Int, or Long (${value!!::class.simpleName})"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterType.STRING -> {
|
||||||
|
when (value) {
|
||||||
|
null -> stmt.setNull(index, Types.NULL)
|
||||||
|
is String -> stmt.setString(index, value)
|
||||||
|
else -> stmt.setString(index, value.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterType.JSON -> stmt.setObject(index, value as String, Types.OTHER)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString() =
|
override fun toString() =
|
||||||
"$type[$name] = $value"
|
"$type[$name] = $value"
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ 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 java.sql.Types
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@ -58,7 +57,7 @@ object Parameters {
|
|||||||
*/
|
*/
|
||||||
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, "?") }
|
||||||
.also(::println)
|
|
||||||
/**
|
/**
|
||||||
* Apply the given parameters to the given query, returning a prepared statement
|
* Apply the given parameters to the given query, returning a prepared statement
|
||||||
*
|
*
|
||||||
@ -69,6 +68,7 @@ object Parameters {
|
|||||||
* @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
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
conn.prepareStatement(query)
|
conn.prepareStatement(query)
|
||||||
} catch (ex: SQLException) {
|
} catch (ex: SQLException) {
|
||||||
@ -88,34 +88,9 @@ object Parameters {
|
|||||||
replaceNamesInQuery(query, parameters)
|
replaceNamesInQuery(query, parameters)
|
||||||
.let { conn.prepareStatement(it) }
|
.let { conn.prepareStatement(it) }
|
||||||
.also { stmt ->
|
.also { stmt ->
|
||||||
replacements.sortedBy { it.first }.map { it.second }.forEachIndexed { index, param ->
|
replacements.sortedBy { it.first }
|
||||||
val idx = index + 1
|
.map { it.second }
|
||||||
when (param.type) {
|
.forEachIndexed { index, param -> param.bind(stmt, index + 1) }
|
||||||
ParameterType.NUMBER -> {
|
|
||||||
when (param.value) {
|
|
||||||
null -> stmt.setNull(idx, Types.NULL)
|
|
||||||
is Byte -> stmt.setByte(idx, param.value)
|
|
||||||
is Short -> stmt.setShort(idx, param.value)
|
|
||||||
is Int -> stmt.setInt(idx, param.value)
|
|
||||||
is Long -> stmt.setLong(idx, param.value)
|
|
||||||
else -> throw DocumentException(
|
|
||||||
"Number parameter must be Byte, Short, Int, or Long " +
|
|
||||||
"(${param.value::class.simpleName})"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterType.STRING -> {
|
|
||||||
when (param.value) {
|
|
||||||
null -> stmt.setNull(idx, Types.NULL)
|
|
||||||
is String -> stmt.setString(idx, param.value)
|
|
||||||
else -> stmt.setString(idx, param.value.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ParameterType.JSON -> stmt.setObject(idx, param.value as String, Types.OTHER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (ex: SQLException) {
|
} catch (ex: SQLException) {
|
||||||
throw DocumentException("Error creating query / binding parameters: ${ex.message}", ex)
|
throw DocumentException("Error creating query / binding parameters: ${ex.message}", ex)
|
||||||
|
@ -2,94 +2,165 @@ package solutions.bitbadger.documents
|
|||||||
|
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for the `Comparison` class
|
* Unit tests for the `ComparisonBetween` class
|
||||||
*/
|
*/
|
||||||
@DisplayName("Comparison")
|
@DisplayName("ComparisonBetween")
|
||||||
class ComparisonTest {
|
class ComparisonBetweenTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("op is set to BETWEEN")
|
||||||
|
fun op() =
|
||||||
|
assertEquals(Op.BETWEEN, ComparisonBetween(Pair(0, 0)).op, "Between comparison should have BETWEEN op")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is false with strings")
|
||||||
|
fun isNumericFalseForStringsAndBetween() =
|
||||||
|
assertFalse(ComparisonBetween(Pair("eh", "zed")).isNumeric,
|
||||||
|
"A BETWEEN with strings should not be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is true with bytes")
|
||||||
|
fun isNumericTrueForByteAndBetween() =
|
||||||
|
assertTrue(ComparisonBetween(Pair<Byte, Byte>(7, 11)).isNumeric, "A BETWEEN with bytes should be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is true with shorts")
|
||||||
|
fun isNumericTrueForShortAndBetween() =
|
||||||
|
assertTrue(ComparisonBetween(Pair<Short, Short>(0, 9)).isNumeric,
|
||||||
|
"A BETWEEN with shorts should be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is true with ints")
|
||||||
|
fun isNumericTrueForIntAndBetween() =
|
||||||
|
assertTrue(ComparisonBetween(Pair(15, 44)).isNumeric, "A BETWEEN with ints should be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is true with longs")
|
||||||
|
fun isNumericTrueForLongAndBetween() =
|
||||||
|
assertTrue(ComparisonBetween(Pair(9L, 12L)).isNumeric, "A BETWEEN with longs should be numeric")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `ComparisonIn` class
|
||||||
|
*/
|
||||||
|
@DisplayName("ComparisonIn")
|
||||||
|
class ComparisonInTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("op is set to IN")
|
||||||
|
fun op() =
|
||||||
|
assertEquals(Op.IN, ComparisonIn(listOf<String>()).op, "In comparison should have IN op")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is false for empty list of values")
|
@DisplayName("isNumeric is false for empty list of values")
|
||||||
fun isNumericFalseForEmptyList() =
|
fun isNumericFalseForEmptyList() =
|
||||||
assertFalse(InComparison(Op.IN, listOf<Int>()).isNumeric, "An IN with empty list should not be numeric")
|
assertFalse(ComparisonIn(listOf<Int>()).isNumeric, "An IN with empty list should not be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is false for IN with strings")
|
@DisplayName("isNumeric is false with strings")
|
||||||
fun isNumericFalseForStringsAndIn() =
|
fun isNumericFalseForStringsAndIn() =
|
||||||
assertFalse(InComparison(Op.IN, listOf("a", "b", "c")).isNumeric, "An IN with strings should not be numeric")
|
assertFalse(ComparisonIn(listOf("a", "b", "c")).isNumeric, "An IN with strings should not be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for IN with bytes")
|
@DisplayName("isNumeric is true with bytes")
|
||||||
fun isNumericTrueForByteAndIn() =
|
fun isNumericTrueForByteAndIn() =
|
||||||
assertTrue(InComparison(Op.IN, listOf<Byte>(4, 8)).isNumeric, "An IN with bytes should be numeric")
|
assertTrue(ComparisonIn(listOf<Byte>(4, 8)).isNumeric, "An IN with bytes should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for IN with shorts")
|
@DisplayName("isNumeric is true with shorts")
|
||||||
fun isNumericTrueForShortAndIn() =
|
fun isNumericTrueForShortAndIn() =
|
||||||
assertTrue(InComparison(Op.IN, listOf<Short>(18, 22)).isNumeric, "An IN with shorts should be numeric")
|
assertTrue(ComparisonIn(listOf<Short>(18, 22)).isNumeric, "An IN with shorts should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for IN with ints")
|
@DisplayName("isNumeric is true with ints")
|
||||||
fun isNumericTrueForIntAndIn() =
|
fun isNumericTrueForIntAndIn() =
|
||||||
assertTrue(InComparison(Op.IN, listOf(7, 8, 9)).isNumeric, "An IN with ints should be numeric")
|
assertTrue(ComparisonIn(listOf(7, 8, 9)).isNumeric, "An IN with ints should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for IN with longs")
|
@DisplayName("isNumeric is true with longs")
|
||||||
fun isNumericTrueForLongAndIn() =
|
fun isNumericTrueForLongAndIn() =
|
||||||
assertTrue(InComparison(Op.IN, listOf(3L)).isNumeric, "An IN with longs should be numeric")
|
assertTrue(ComparisonIn(listOf(3L)).isNumeric, "An IN with longs should be numeric")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `ComparisonInArray` class
|
||||||
|
*/
|
||||||
|
@DisplayName("ComparisonInArray")
|
||||||
|
class ComparisonInArrayTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is false for BETWEEN with strings")
|
@DisplayName("op is set to IN_ARRAY")
|
||||||
fun isNumericFalseForStringsAndBetween() =
|
fun op() =
|
||||||
assertFalse(BetweenComparison(Op.BETWEEN, Pair("eh", "zed")).isNumeric,
|
assertEquals(
|
||||||
"A BETWEEN with strings should not be numeric")
|
Op.IN_ARRAY,
|
||||||
|
ComparisonInArray(Pair(TEST_TABLE, listOf<String>())).op,
|
||||||
|
"InArray comparison should have IN_ARRAY op"
|
||||||
|
)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for BETWEEN with bytes")
|
@DisplayName("isNumeric is false for empty list of values")
|
||||||
fun isNumericTrueForByteAndBetween() =
|
fun isNumericFalseForEmptyList() =
|
||||||
assertTrue(BetweenComparison(Op.BETWEEN, Pair<Byte, Byte>(7, 11)).isNumeric, "A BETWEEN with bytes should be numeric")
|
assertFalse(ComparisonIn(listOf<Int>()).isNumeric, "An IN_ARRAY with empty list should not be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for BETWEEN with shorts")
|
@DisplayName("isNumeric is false with strings")
|
||||||
fun isNumericTrueForShortAndBetween() =
|
fun isNumericFalseForStringsAndIn() =
|
||||||
assertTrue(BetweenComparison(Op.BETWEEN, Pair<Short, Short>(0, 9)).isNumeric,
|
assertFalse(ComparisonIn(listOf("a", "b", "c")).isNumeric, "An IN_ARRAY with strings should not be numeric")
|
||||||
"A BETWEEN with shorts should be numeric")
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for BETWEEN with ints")
|
@DisplayName("isNumeric is false with bytes")
|
||||||
fun isNumericTrueForIntAndBetween() =
|
fun isNumericTrueForByteAndIn() =
|
||||||
assertTrue(BetweenComparison(Op.BETWEEN, Pair(15, 44)).isNumeric, "A BETWEEN with ints should be numeric")
|
assertTrue(ComparisonIn(listOf<Byte>(4, 8)).isNumeric, "An IN_ARRAY with bytes should not be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for BETWEEN with longs")
|
@DisplayName("isNumeric is false with shorts")
|
||||||
fun isNumericTrueForLongAndBetween() =
|
fun isNumericTrueForShortAndIn() =
|
||||||
assertTrue(BetweenComparison(Op.BETWEEN, Pair(9L, 12L)).isNumeric, "A BETWEEN with longs should be numeric")
|
assertTrue(ComparisonIn(listOf<Short>(18, 22)).isNumeric, "An IN_ARRAY with shorts should not be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is false with ints")
|
||||||
|
fun isNumericTrueForIntAndIn() =
|
||||||
|
assertTrue(ComparisonIn(listOf(7, 8, 9)).isNumeric, "An IN_ARRAY with ints should not be numeric")
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("isNumeric is false with longs")
|
||||||
|
fun isNumericTrueForLongAndIn() =
|
||||||
|
assertTrue(ComparisonIn(listOf(3L)).isNumeric, "An IN_ARRAY with longs should not be numeric")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit tests for the `ComparisonSingle` class
|
||||||
|
*/
|
||||||
|
@DisplayName("ComparisonSingle")
|
||||||
|
class ComparisonSingleTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is false for string value")
|
@DisplayName("isNumeric is false for string value")
|
||||||
fun isNumericFalseForString() =
|
fun isNumericFalseForString() =
|
||||||
assertFalse(SingleComparison(Op.EQUAL, "80").isNumeric, "A string should not be numeric")
|
assertFalse(ComparisonSingle(Op.EQUAL, "80").isNumeric, "A string should not be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for byte value")
|
@DisplayName("isNumeric is true for byte value")
|
||||||
fun isNumericTrueForByte() =
|
fun isNumericTrueForByte() =
|
||||||
assertTrue(SingleComparison(Op.EQUAL, 47.toByte()).isNumeric, "A byte should be numeric")
|
assertTrue(ComparisonSingle(Op.EQUAL, 47.toByte()).isNumeric, "A byte should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for short value")
|
@DisplayName("isNumeric is true for short value")
|
||||||
fun isNumericTrueForShort() =
|
fun isNumericTrueForShort() =
|
||||||
assertTrue(SingleComparison(Op.EQUAL, 2.toShort()).isNumeric, "A short should be numeric")
|
assertTrue(ComparisonSingle(Op.EQUAL, 2.toShort()).isNumeric, "A short should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for int value")
|
@DisplayName("isNumeric is true for int value")
|
||||||
fun isNumericTrueForInt() =
|
fun isNumericTrueForInt() =
|
||||||
assertTrue(SingleComparison(Op.EQUAL, 555).isNumeric, "An int should be numeric")
|
assertTrue(ComparisonSingle(Op.EQUAL, 555).isNumeric, "An int should be numeric")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("isNumeric is true for long value")
|
@DisplayName("isNumeric is true for long value")
|
||||||
fun isNumericTrueForLong() =
|
fun isNumericTrueForLong() =
|
||||||
assertTrue(SingleComparison(Op.EQUAL, 82L).isNumeric, "A long should be numeric")
|
assertTrue(ComparisonSingle(Op.EQUAL, 82L).isNumeric, "A long should be numeric")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user