Collapse into top-level module

This commit is contained in:
2025-02-17 12:15:43 -05:00
parent 4249159252
commit b1a9910d50
32 changed files with 37 additions and 40 deletions

View File

@@ -1,160 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotEquals
import kotlin.test.assertTrue
class AutoIdTest {
@Test
@DisplayName("Generates a UUID string")
fun 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")
fun generateRandomStringEven() {
val 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")
fun generateRandomStringOdd() {
val result = AutoId.generateRandomString(11)
assertEquals(11, result.length, "There should have been 11 characters in $result")
}
@Test
@DisplayName("Generates different random hex character strings")
fun generateRandomStringIsRandom() {
val result1 = AutoId.generateRandomString(16)
val result2 = AutoId.generateRandomString(16)
assertNotEquals(result1, result2, "There should have been 2 different strings generated")
}
@Test
@DisplayName("needsAutoId fails for null document")
fun needsAutoIdFailsForNullDocument() {
assertThrows<IllegalArgumentException> { AutoId.needsAutoId(AutoId.DISABLED, null, "id") }
}
@Test
@DisplayName("needsAutoId fails for missing ID property")
fun needsAutoIdFailsForMissingId() {
assertThrows<IllegalArgumentException> { AutoId.needsAutoId(AutoId.UUID, IntIdClass(0), "Id") }
}
@Test
@DisplayName("needsAutoId returns false if disabled")
fun needsAutoIdFalseIfDisabled() {
assertFalse(AutoId.needsAutoId(AutoId.DISABLED, "", ""), "Disabled Auto ID should always return false")
}
@Test
@DisplayName("needsAutoId returns true for Number strategy and byte ID of 0")
fun needsAutoIdTrueForByteWithZero() {
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(0), "id"), "Number Auto ID with 0 should return true")
}
@Test
@DisplayName("needsAutoId returns false for Number strategy and byte ID of non-0")
fun needsAutoIdFalseForByteWithNonZero() {
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ByteIdClass(77), "id"),
"Number Auto ID with 77 should return false")
}
@Test
@DisplayName("needsAutoId returns true for Number strategy and short ID of 0")
fun needsAutoIdTrueForShortWithZero() {
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(0), "id"), "Number Auto ID with 0 should return true")
}
@Test
@DisplayName("needsAutoId returns false for Number strategy and short ID of non-0")
fun needsAutoIdFalseForShortWithNonZero() {
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, ShortIdClass(31), "id"),
"Number Auto ID with 31 should return false")
}
@Test
@DisplayName("needsAutoId returns true for Number strategy and int ID of 0")
fun needsAutoIdTrueForIntWithZero() {
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, IntIdClass(0), "id"), "Number Auto ID with 0 should return true")
}
@Test
@DisplayName("needsAutoId returns false for Number strategy and int ID of non-0")
fun needsAutoIdFalseForIntWithNonZero() {
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, IntIdClass(6), "id"), "Number Auto ID with 6 should return false")
}
@Test
@DisplayName("needsAutoId returns true for Number strategy and long ID of 0")
fun needsAutoIdTrueForLongWithZero() {
assertTrue(AutoId.needsAutoId(AutoId.NUMBER, LongIdClass(0), "id"), "Number Auto ID with 0 should return true")
}
@Test
@DisplayName("needsAutoId returns false for Number strategy and long ID of non-0")
fun needsAutoIdFalseForLongWithNonZero() {
assertFalse(AutoId.needsAutoId(AutoId.NUMBER, IntIdClass(2), "id"), "Number Auto ID with 2 should return false")
}
@Test
@DisplayName("needsAutoId fails for Number strategy and non-number ID")
fun needsAutoIdFailsForNumberWithStringId() {
assertThrows<IllegalArgumentException> { AutoId.needsAutoId(AutoId.NUMBER, StringIdClass(""), "id") }
}
@Test
@DisplayName("needsAutoId returns true for UUID strategy and blank ID")
fun needsAutoIdTrueForUUIDWithBlank() {
assertTrue(AutoId.needsAutoId(AutoId.UUID, StringIdClass(""), "id"),
"UUID Auto ID with blank should return true")
}
@Test
@DisplayName("needsAutoId returns false for UUID strategy and non-blank ID")
fun needsAutoIdFalseForUUIDNotBlank() {
assertFalse(AutoId.needsAutoId(AutoId.UUID, StringIdClass("howdy"), "id"),
"UUID Auto ID with non-blank should return false")
}
@Test
@DisplayName("needsAutoId fails for UUID strategy and non-string ID")
fun needsAutoIdFailsForUUIDNonString() {
assertThrows<IllegalArgumentException> { AutoId.needsAutoId(AutoId.UUID, IntIdClass(5), "id") }
}
@Test
@DisplayName("needsAutoId returns true for Random String strategy and blank ID")
fun needsAutoIdTrueForRandomWithBlank() {
assertTrue(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass(""), "id"),
"Random String Auto ID with blank should return true")
}
@Test
@DisplayName("needsAutoId returns false for Random String strategy and non-blank ID")
fun needsAutoIdFalseForRandomNotBlank() {
assertFalse(AutoId.needsAutoId(AutoId.RANDOM_STRING, StringIdClass("full"), "id"),
"Random String Auto ID with non-blank should return false")
}
@Test
@DisplayName("needsAutoId fails for Random String strategy and non-string ID")
fun needsAutoIdFailsForRandomNonString() {
assertThrows<IllegalArgumentException> { AutoId.needsAutoId(AutoId.RANDOM_STRING, ShortIdClass(55), "id") }
}
}
data class ByteIdClass(var id: Byte)
data class ShortIdClass(var id: Short)
data class IntIdClass(var id: Int)
data class LongIdClass(var id: Long)
data class StringIdClass(var id: String)

View File

@@ -1,26 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class ConfigurationTest {
@Test
@DisplayName("Default ID field is `id`")
fun defaultIdField() {
assertEquals("id", Configuration.idField, "Default ID field incorrect")
}
@Test
@DisplayName("Default Auto ID strategy is `DISABLED`")
fun defaultAutoId() {
assertEquals(AutoId.DISABLED, Configuration.autoIdStrategy, "Default Auto ID strategy should be `disabled`")
}
@Test
@DisplayName("Default ID string length should be 16")
fun defaultIdStringLength() {
assertEquals(16, Configuration.idStringLength, "Default ID string length should be 16")
}
}

View File

@@ -1,20 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class FieldMatchTest {
@Test
@DisplayName("ANY uses proper SQL")
fun any() {
assertEquals("OR", FieldMatch.ANY.sql, "ANY should use OR")
}
@Test
@DisplayName("ALL uses proper SQL")
fun all() {
assertEquals("AND", FieldMatch.ALL.sql, "ALL should use AND")
}
}

View File

@@ -1,277 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
class FieldTest {
@Test
@DisplayName("equal constructs a field")
fun equalCtor() {
val field = Field.equal("Test", 14)
assertEquals("Test", field.name, "Field name not filled correctly")
assertEquals(Op.EQUAL, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals(14, field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("greater constructs a field")
fun greaterCtor() {
val field = Field.greater("Great", "night")
assertEquals("Great", field.name, "Field name not filled correctly")
assertEquals(Op.GREATER, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("night", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("greaterOrEqual constructs a field")
fun greaterOrEqualCtor() {
val field = Field.greaterOrEqual("Nice", 88L)
assertEquals("Nice", field.name, "Field name not filled correctly")
assertEquals(Op.GREATER_OR_EQUAL, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals(88L, field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("less constructs a field")
fun lessCtor() {
val field = Field.less("Lesser", "seven")
assertEquals("Lesser", field.name, "Field name not filled correctly")
assertEquals(Op.LESS, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("seven", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("lessOrEqual constructs a field")
fun lessOrEqualCtor() {
val field = Field.lessOrEqual("Nobody", "KNOWS")
assertEquals("Nobody", field.name, "Field name not filled correctly")
assertEquals(Op.LESS_OR_EQUAL, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("KNOWS", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("notEqual constructs a field")
fun notEqualCtor() {
val field = Field.notEqual("Park", "here")
assertEquals("Park", field.name, "Field name not filled correctly")
assertEquals(Op.NOT_EQUAL, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("here", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("between constructs a field")
fun betweenCtor() {
val field = Field.between("Age", 18, 49)
assertEquals("Age", field.name, "Field name not filled correctly")
assertEquals(Op.BETWEEN, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals(18, field.comparison.value.first, "Field comparison min value not filled correctly")
assertEquals(49, field.comparison.value.second, "Field comparison max value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("any constructs a field")
fun inCtor() {
val field = Field.any("Here", listOf(8, 16, 32))
assertEquals("Here", field.name, "Field name not filled correctly")
assertEquals(Op.IN, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals(listOf(8, 16, 32), field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("inArray constructs a field")
fun inArrayCtor() {
val field = Field.inArray("ArrayField", "table", listOf("z"))
assertEquals("ArrayField", field.name, "Field name not filled correctly")
assertEquals(Op.IN_ARRAY, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("table", field.comparison.value.first, "Field comparison table not filled correctly")
assertEquals(listOf("z"), field.comparison.value.second, "Field comparison values not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("exists constructs a field")
fun existsCtor() {
val field = Field.exists("Groovy")
assertEquals("Groovy", field.name, "Field name not filled correctly")
assertEquals(Op.EXISTS, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("notExists constructs a field")
fun notExistsCtor() {
val field = Field.notExists("Groovy")
assertEquals("Groovy", field.name, "Field name not filled correctly")
assertEquals(Op.NOT_EXISTS, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("named constructs a field")
fun namedCtor() {
val field = Field.named("Tacos")
assertEquals("Tacos", field.name, "Field name not filled correctly")
assertEquals(Op.EQUAL, field.comparison.op, "Field comparison operation not filled correctly")
assertEquals("", field.comparison.value, "Field comparison value not filled correctly")
assertNull(field.parameterName, "The parameter name should have been null")
assertNull(field.qualifier, "The qualifier should have been null")
}
@Test
@DisplayName("nameToPath creates a simple PostgreSQL SQL name")
fun nameToPathPostgresSimpleSQL() {
assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.SQL),
"Path not constructed correctly")
}
@Test
@DisplayName("nameToPath creates a simple SQLite SQL name")
fun nameToPathSQLiteSimpleSQL() {
assertEquals("data->>'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.SQL),
"Path not constructed correctly")
}
@Test
@DisplayName("nameToPath creates a nested PostgreSQL SQL name")
fun 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")
fun 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")
fun nameToPathPostgresSimpleJSON() {
assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.POSTGRESQL, FieldFormat.JSON),
"Path not constructed correctly")
}
@Test
@DisplayName("nameToPath creates a simple SQLite JSON name")
fun nameToPathSQLiteSimpleJSON() {
assertEquals("data->'Simple'", Field.nameToPath("Simple", Dialect.SQLITE, FieldFormat.JSON),
"Path not constructed correctly")
}
@Test
@DisplayName("nameToPath creates a nested PostgreSQL JSON name")
fun 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")
fun 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")
}
@Test
@DisplayName("withParameterName adjusts the parameter name")
fun withParameterName() {
assertEquals(":name", Field.equal("Bob", "Tom").withParameterName(":name").parameterName,
"Parameter name not filled correctly")
}
@Test
@DisplayName("withQualifier adjust the table qualifier")
fun withQualifier() {
assertEquals("joe", Field.equal("Bill", "Matt").withQualifier("joe").qualifier,
"Qualifier not filled correctly")
}
@Test
@DisplayName("path generates for simple unqualified PostgreSQL field")
fun 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")
fun 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")
fun 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")
fun 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")
fun 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")
fun 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")
fun 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")
fun pathSQLiteNestedQualified() {
assertEquals("bird.data->'Nest'->>'Away'",
Field.equal("Nest.Away", "doc").withQualifier("bird").path(Dialect.SQLITE, FieldFormat.SQL),
"Path not correct")
}
}

View File

@@ -1,74 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class OpTest {
@Test
@DisplayName("EQUAL uses proper SQL")
fun equalSQL() {
assertEquals("=", Op.EQUAL.sql, "The SQL for equal is incorrect")
}
@Test
@DisplayName("GREATER uses proper SQL")
fun greaterSQL() {
assertEquals(">", Op.GREATER.sql, "The SQL for greater is incorrect")
}
@Test
@DisplayName("GREATER_OR_EQUAL uses proper SQL")
fun greaterOrEqualSQL() {
assertEquals(">=", Op.GREATER_OR_EQUAL.sql, "The SQL for greater-or-equal is incorrect")
}
@Test
@DisplayName("LESS uses proper SQL")
fun lessSQL() {
assertEquals("<", Op.LESS.sql, "The SQL for less is incorrect")
}
@Test
@DisplayName("LESS_OR_EQUAL uses proper SQL")
fun lessOrEqualSQL() {
assertEquals("<=", Op.LESS_OR_EQUAL.sql, "The SQL for less-or-equal is incorrect")
}
@Test
@DisplayName("NOT_EQUAL uses proper SQL")
fun notEqualSQL() {
assertEquals("<>", Op.NOT_EQUAL.sql, "The SQL for not-equal is incorrect")
}
@Test
@DisplayName("BETWEEN uses proper SQL")
fun betweenSQL() {
assertEquals("BETWEEN", Op.BETWEEN.sql, "The SQL for between is incorrect")
}
@Test
@DisplayName("IN uses proper SQL")
fun inSQL() {
assertEquals("IN", Op.IN.sql, "The SQL for in is incorrect")
}
@Test
@DisplayName("IN_ARRAY uses proper SQL")
fun inArraySQL() {
assertEquals("?|", Op.IN_ARRAY.sql, "The SQL for in-array is incorrect")
}
@Test
@DisplayName("EXISTS uses proper SQL")
fun existsSQL() {
assertEquals("IS NOT NULL", Op.EXISTS.sql, "The SQL for exists is incorrect")
}
@Test
@DisplayName("NOT_EXISTS uses proper SQL")
fun notExistsSQL() {
assertEquals("IS NULL", Op.NOT_EXISTS.sql, "The SQL for not-exists is incorrect")
}
}

View File

@@ -1,26 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class ParameterNameTest {
@Test
@DisplayName("derive works when given existing names")
fun withExisting() {
val names = 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")
fun allAnonymous() {
val names = 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")
}
}

View File

@@ -1,34 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.assertThrows
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
class ParameterTest {
@Test
@DisplayName("Construction with colon-prefixed name")
fun ctorWithColon() {
val p = Parameter(":test", ParameterType.STRING, "ABC")
assertEquals(":test", p.name, "Parameter name was incorrect")
assertEquals(ParameterType.STRING, p.type, "Parameter type was incorrect")
assertEquals("ABC", p.value, "Parameter value was incorrect")
}
@Test
@DisplayName("Construction with at-sign-prefixed name")
fun ctorWithAtSign() {
val p = Parameter("@yo", ParameterType.NUMBER, null)
assertEquals("@yo", p.name, "Parameter name was incorrect")
assertEquals(ParameterType.NUMBER, p.type, "Parameter type was incorrect")
assertNull(p.value, "Parameter value was incorrect")
}
@Test
@DisplayName("Construction fails with incorrect prefix")
fun ctorFailsForPrefix() {
assertThrows<DocumentException> { Parameter("it", ParameterType.JSON, "") }
}
}

View File

@@ -1,18 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import kotlin.test.Test
import kotlin.test.assertEquals
class ParametersTest {
@Test
@DisplayName("replaceNamesInQuery replaces successfully")
fun replaceNamesInQuery() {
val parameters = listOf(Parameter(":data", ParameterType.JSON, "{}"),
Parameter(":data_ext", ParameterType.STRING, ""))
val 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")
}
}

View File

@@ -1,197 +0,0 @@
package solutions.bitbadger.documents.common
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class QueryTest {
/** Test table name */
private val tbl = "test_table"
@Test
@DisplayName("statementWhere generates correctly")
fun statementWhere() {
assertEquals("x WHERE y", Query.statementWhere("x", "y"), "Statements not combined correctly")
}
@Test
@DisplayName("Definition.ensureTableFor generates correctly")
fun ensureTableFor() {
assertEquals("CREATE TABLE IF NOT EXISTS my.table (data JSONB NOT NULL)",
Query.Definition.ensureTableFor("my.table", "JSONB"), "CREATE TABLE statement not constructed correctly")
}
@Test
@DisplayName("Definition.ensureKey generates correctly with schema")
fun ensureKeyWithSchema() {
assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data->>'id'))",
Query.Definition.ensureKey("test.table", Dialect.POSTGRESQL),
"CREATE INDEX for key statement with schema not constructed correctly")
}
@Test
@DisplayName("Definition.ensureKey generates correctly without schema")
fun ensureKeyWithoutSchema() {
assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_${tbl}_key ON $tbl ((data->>'id'))",
Query.Definition.ensureKey(tbl, Dialect.SQLITE),
"CREATE INDEX for key statement without schema not constructed correctly")
}
@Test
@DisplayName("Definition.ensureIndexOn generates multiple fields and directions")
fun ensureIndexOnMultipleFields() {
assertEquals(
"CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table ((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)",
Query.Definition.ensureIndexOn("test.table", "gibberish", listOf("taco", "guac DESC", "salsa ASC"),
Dialect.POSTGRESQL),
"CREATE INDEX for multiple field statement not constructed correctly")
}
@Test
@DisplayName("Definition.ensureIndexOn generates nested PostgreSQL field")
fun ensureIndexOnNestedPostgres() {
assertEquals("CREATE INDEX IF NOT EXISTS idx_${tbl}_nest ON $tbl ((data#>>'{a,b,c}'))",
Query.Definition.ensureIndexOn(tbl, "nest", listOf("a.b.c"), Dialect.POSTGRESQL),
"CREATE INDEX for nested PostgreSQL field incorrect")
}
@Test
@DisplayName("Definition.ensureIndexOn generates nested SQLite field")
fun ensureIndexOnNestedSQLite() {
assertEquals("CREATE INDEX IF NOT EXISTS idx_${tbl}_nest ON $tbl ((data->'a'->'b'->>'c'))",
Query.Definition.ensureIndexOn(tbl, "nest", listOf("a.b.c"), Dialect.SQLITE),
"CREATE INDEX for nested SQLite field incorrect")
}
@Test
@DisplayName("insert generates correctly")
fun insert() {
try {
Configuration.connectionString = "postgresql"
assertEquals(
"INSERT INTO $tbl VALUES (:data)",
Query.insert(tbl),
"INSERT statement not constructed correctly"
)
} finally {
Configuration.connectionString = null
}
}
@Test
@DisplayName("save generates correctly")
fun save() {
try {
Configuration.connectionString = "postgresql"
assertEquals(
"INSERT INTO $tbl VALUES (:data) ON CONFLICT ((data->>'id')) DO UPDATE SET data = EXCLUDED.data",
Query.save(tbl), "INSERT ON CONFLICT UPDATE statement not constructed correctly"
)
} finally {
Configuration.connectionString = null
}
}
@Test
@DisplayName("count generates correctly")
fun count() {
assertEquals("SELECT COUNT(*) AS it FROM $tbl", Query.count(tbl), "Count query not constructed correctly")
}
@Test
@DisplayName("exists generates correctly")
fun exists() {
assertEquals("SELECT EXISTS (SELECT 1 FROM $tbl WHERE turkey) AS it", Query.exists(tbl, "turkey"),
"Exists query not constructed correctly")
}
@Test
@DisplayName("find generates correctly")
fun find() {
assertEquals("SELECT data FROM $tbl", Query.find(tbl), "Find query not constructed correctly")
}
@Test
@DisplayName("update generates successfully")
fun update() {
assertEquals("UPDATE $tbl SET data = :data", Query.update(tbl), "Update query not constructed correctly")
}
@Test
@DisplayName("delete generates successfully")
fun delete() {
assertEquals("DELETE FROM $tbl", Query.delete(tbl), "Delete query not constructed correctly")
}
@Test
@DisplayName("orderBy generates for no fields")
fun orderByNone() {
assertEquals("", Query.orderBy(listOf(), Dialect.POSTGRESQL), "ORDER BY should have been blank (PostgreSQL)")
assertEquals("", Query.orderBy(listOf(), Dialect.SQLITE), "ORDER BY should have been blank (SQLite)")
}
@Test
@DisplayName("orderBy generates single, no direction for PostgreSQL")
fun orderBySinglePostgres() {
assertEquals(" ORDER BY data->>'TestField'",
Query.orderBy(listOf(Field.named("TestField")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates single, no direction for SQLite")
fun orderBySingleSQLite() {
assertEquals(" ORDER BY data->>'TestField'", Query.orderBy(listOf(Field.named("TestField")), Dialect.SQLITE),
"ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates multiple with direction for PostgreSQL")
fun orderByMultiplePostgres() {
assertEquals(" ORDER BY data#>>'{Nested,Test,Field}' DESC, data->>'AnotherField', data->>'It' DESC",
Query.orderBy(
listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")),
Dialect.POSTGRESQL),
"ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates multiple with direction for SQLite")
fun orderByMultipleSQLite() {
assertEquals(" ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC",
Query.orderBy(
listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")),
Dialect.SQLITE),
"ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates numeric ordering PostgreSQL")
fun orderByNumericPostgres() {
assertEquals(" ORDER BY (data->>'Test')::numeric",
Query.orderBy(listOf(Field.named("n:Test")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates numeric ordering for SQLite")
fun orderByNumericSQLite() {
assertEquals(" ORDER BY data->>'Test'", Query.orderBy(listOf(Field.named("n:Test")), Dialect.SQLITE),
"ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates case-insensitive ordering for PostgreSQL")
fun orderByCIPostgres() {
assertEquals(" ORDER BY LOWER(data#>>'{Test,Field}') DESC NULLS FIRST",
Query.orderBy(listOf(Field.named("i:Test.Field DESC NULLS FIRST")), Dialect.POSTGRESQL),
"ORDER BY not constructed correctly")
}
@Test
@DisplayName("orderBy generates case-insensitive ordering for SQLite")
fun orderByCISQLite() {
assertEquals(" ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST",
Query.orderBy(listOf(Field.named("i:Test.Field ASC NULLS LAST")), Dialect.SQLITE),
"ORDER BY not constructed correctly")
}
}