Initial Development #1

Merged
danieljsummers merged 88 commits from v1-rc into main 2025-04-16 01:29:20 +00:00
6 changed files with 173 additions and 50 deletions
Showing only changes of commit 2b6dff9fd3 - Show all commits

1
.idea/misc.xml generated
View File

@ -6,6 +6,7 @@
<list> <list>
<option value="$PROJECT_DIR$/src/common/pom.xml" /> <option value="$PROJECT_DIR$/src/common/pom.xml" />
<option value="$PROJECT_DIR$/src/sqlite/pom.xml" /> <option value="$PROJECT_DIR$/src/sqlite/pom.xml" />
<option value="$PROJECT_DIR$/pom.xml" />
</list> </list>
</option> </option>
<option name="ignoredFiles"> <option name="ignoredFiles">

View File

@ -14,7 +14,7 @@ class Comparison<T>(val op: Op, val value: T) {
val toCheck = when (op) { val toCheck = when (op) {
Op.IN -> { Op.IN -> {
val values = value as? Collection<*> val values = value as? Collection<*>
if (values.isNullOrEmpty()) "" else values.elementAt(0) if (values.isNullOrEmpty()) "" else values.elementAt(0)
} }
Op.BETWEEN -> (value as Pair<*, *>).first Op.BETWEEN -> (value as Pair<*, *>).first
else -> value else -> value

View File

@ -21,7 +21,11 @@ object Parameters {
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 {
if (it.name.isBlank()) it.withParameterName(name.derive(null)) else it if (it.parameterName.isNullOrEmpty() && !listOf(Op.EXISTS, Op.NOT_EXISTS).contains(it.comparison.op)) {
it.withParameterName(name.derive(null))
} else {
it
}
} }
} }
@ -75,7 +79,8 @@ object Parameters {
is Int -> stmt.setInt(idx, param.value) is Int -> stmt.setInt(idx, param.value)
is Long -> stmt.setLong(idx, param.value) is Long -> stmt.setLong(idx, param.value)
else -> throw DocumentException( else -> throw DocumentException(
"Number parameter must be Byte, Short, Int, or Long (${param.value::class.simpleName})") "Number parameter must be Byte, Short, Int, or Long " +
"(${param.value::class.simpleName})")
} }
} }
ParameterType.STRING -> { ParameterType.STRING -> {

View File

@ -16,7 +16,7 @@ object Results {
* @param rs A `ResultSet` set to the row with the document to be constructed * @param rs A `ResultSet` set to the row with the document to be constructed
* @return The constructed domain item * @return The constructed domain item
*/ */
inline fun <reified TDoc> fromDocument(field: String, rs: ResultSet): TDoc = inline fun <reified TDoc> fromDocument(field: String, rs: ResultSet) =
Configuration.json.decodeFromString<TDoc>(rs.getString(field)) Configuration.json.decodeFromString<TDoc>(rs.getString(field))
/** /**
@ -25,8 +25,8 @@ object Results {
* @param rs A `ResultSet` set to the row with the document to be constructed< * @param rs A `ResultSet` set to the row with the document to be constructed<
* @return The constructed domain item * @return The constructed domain item
*/ */
inline fun <reified TDoc> fromData(rs: ResultSet): TDoc = inline fun <reified TDoc> fromData(rs: ResultSet) =
fromDocument("data", rs) fromDocument<TDoc>("data", rs)
/** /**
* Create a list of items for the results of the given command, using the specified mapping function * Create a list of items for the results of the given command, using the specified mapping function
@ -36,7 +36,7 @@ object Results {
* @return A list of items from the query's result * @return A list of items from the query's result
* @throws DocumentException If there is a problem executing the query * @throws DocumentException If there is a problem executing the query
*/ */
inline fun <reified TDoc> toCustomList(stmt: PreparedStatement, mapFunc: (ResultSet) -> TDoc): List<TDoc> = inline fun <reified TDoc> toCustomList(stmt: PreparedStatement, mapFunc: (ResultSet) -> TDoc) =
try { try {
stmt.executeQuery().use { stmt.executeQuery().use {
val results = mutableListOf<TDoc>() val results = mutableListOf<TDoc>()
@ -55,7 +55,7 @@ object Results {
* @param rs A `ResultSet` set to the row with the count to retrieve * @param rs A `ResultSet` set to the row with the count to retrieve
* @return The count from the row * @return The count from the row
*/ */
fun toCount(rs: ResultSet): Long = fun toCount(rs: ResultSet) =
when (Configuration.dialect()) { when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getInt("it").toLong() Dialect.POSTGRESQL -> rs.getInt("it").toLong()
Dialect.SQLITE -> rs.getLong("it") Dialect.SQLITE -> rs.getLong("it")
@ -67,7 +67,7 @@ object Results {
* @param rs A `ResultSet` set to the row with the true/false value to retrieve * @param rs A `ResultSet` set to the row with the true/false value to retrieve
* @return The true/false value from the row * @return The true/false value from the row
*/ */
fun toExists(rs: ResultSet): Boolean = fun toExists(rs: ResultSet) =
when (Configuration.dialect()) { when (Configuration.dialect()) {
Dialect.POSTGRESQL -> rs.getBoolean("it") Dialect.POSTGRESQL -> rs.getBoolean("it")
Dialect.SQLITE -> toCount(rs) > 0L Dialect.SQLITE -> toCount(rs) > 0L

View File

@ -3,9 +3,37 @@ package solutions.bitbadger.documents
import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.DisplayName
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotSame
import kotlin.test.assertSame
class ParametersTest { class ParametersTest {
@Test
@DisplayName("nameFields works with no changes")
fun nameFieldsNoChange() {
val fields = listOf(Field.equal("a", "", ":test"), Field.exists("q"), Field.equal("b", "", ":me"))
val named = Parameters.nameFields(fields)
assertEquals(fields.size, named.size, "There should have been 3 fields in the list")
assertSame(fields.elementAt(0), named.elementAt(0), "The first field should be the same")
assertSame(fields.elementAt(1), named.elementAt(1), "The second field should be the same")
assertSame(fields.elementAt(2), named.elementAt(2), "The third field should be the same")
}
@Test
@DisplayName("nameFields works when changing fields")
fun nameFieldsChange() {
val fields = listOf(
Field.equal("a", ""), Field.equal("e", "", ":hi"), Field.equal("b", ""), Field.notExists("z"))
val named = Parameters.nameFields(fields)
assertEquals(fields.size, named.size, "There should have been 4 fields in the list")
assertNotSame(fields.elementAt(0), named.elementAt(0), "The first field should not be the same")
assertEquals(":field0", named.elementAt(0).parameterName, "First parameter name incorrect")
assertSame(fields.elementAt(1), named.elementAt(1), "The second field should be the same")
assertNotSame(fields.elementAt(2), named.elementAt(2), "The third field should not be the same")
assertEquals(":field1", named.elementAt(2).parameterName, "Third parameter name incorrect")
assertSame(fields.elementAt(3), named.elementAt(3), "The fourth field should be the same")
}
@Test @Test
@DisplayName("replaceNamesInQuery replaces successfully") @DisplayName("replaceNamesInQuery replaces successfully")
fun replaceNamesInQuery() { fun replaceNamesInQuery() {

View File

@ -10,6 +10,12 @@ class QueryTest {
/** Test table name */ /** Test table name */
private val tbl = "test_table" private val tbl = "test_table"
/** Dummy connection string for PostgreSQL */
private val pg = ":postgresql:"
/** Dummy connection string for SQLite */
private val lite = ":sqlite:"
/** /**
* Clear the connection string (resets Dialect) * Clear the connection string (resets Dialect)
*/ */
@ -20,70 +26,166 @@ class QueryTest {
@Test @Test
@DisplayName("statementWhere generates correctly") @DisplayName("statementWhere generates correctly")
fun statementWhere() { fun statementWhere() =
assertEquals("x WHERE y", Query.statementWhere("x", "y"), "Statements not combined correctly") assertEquals("x WHERE y", Query.statementWhere("x", "y"), "Statements not combined correctly")
// ~~~ Where ~~~
@Test
@DisplayName("Where.byFields is blank when given no fields")
fun whereByFieldsBlankIfEmpty() =
assertEquals("", Query.Where.byFields(listOf()))
@Test
@DisplayName("Where.byFields generates one numeric field (PostgreSQL)")
fun whereByFieldsOneFieldPostgres() {
Configuration.connectionString = pg
assertEquals("(data->>'it')::numeric = :that", Query.Where.byFields(listOf(Field.equal("it", 9, ":that"))))
} }
@Test
@DisplayName("Where.byFields generates one alphanumeric field (PostgreSQL)")
fun whereByFieldsOneAlphaFieldPostgres() {
Configuration.connectionString = pg
assertEquals("data->>'it' = :that", Query.Where.byFields(listOf(Field.equal("it", "", ":that"))))
}
@Test
@DisplayName("Where.byFields generates one field (SQLite)")
fun whereByFieldsOneFieldSQLite() {
Configuration.connectionString = lite
assertEquals("data->>'it' = :that", Query.Where.byFields(listOf(Field.equal("it", "", ":that"))))
}
@Test
@DisplayName("Where.byFields generates multiple fields w/ default match (PostgreSQL)")
fun whereByFieldsMultipleDefaultPostgres() {
Configuration.connectionString = pg
assertEquals("data->>'1' = :one AND (data->>'2')::numeric = :two AND data->>'3' = :three",
Query.Where.byFields(
listOf(Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three"))))
}
@Test
@DisplayName("Where.byFields generates multiple fields w/ default match (SQLite)")
fun whereByFieldsMultipleDefaultSQLite() {
Configuration.connectionString = lite
assertEquals("data->>'1' = :one AND data->>'2' = :two AND data->>'3' = :three",
Query.Where.byFields(
listOf(Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three"))))
}
@Test
@DisplayName("Where.byFields generates multiple fields w/ ANY match (PostgreSQL)")
fun whereByFieldsMultipleAnyPostgres() {
Configuration.connectionString = pg
assertEquals("data->>'1' = :one OR (data->>'2')::numeric = :two OR data->>'3' = :three",
Query.Where.byFields(
listOf(Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")),
FieldMatch.ANY))
}
@Test
@DisplayName("Where.byFields generates multiple fields w/ ANY match (SQLite)")
fun whereByFieldsMultipleAnySQLite() {
Configuration.connectionString = lite
assertEquals("data->>'1' = :one OR data->>'2' = :two OR data->>'3' = :three",
Query.Where.byFields(
listOf(Field.equal("1", "", ":one"), Field.equal("2", 0L, ":two"), Field.equal("3", "", ":three")),
FieldMatch.ANY))
}
@Test
@DisplayName("Where.byId generates defaults for alphanumeric key (PostgreSQL)")
fun whereByIdDefaultAlphaPostgres() {
Configuration.connectionString = pg
assertEquals("data->>'id' = :id", Query.Where.byId(docId = ""))
}
@Test
@DisplayName("Where.byId generates defaults for numeric key (PostgreSQL)")
fun whereByIdDefaultNumericPostgres() {
Configuration.connectionString = pg
assertEquals("(data->>'id')::numeric = :id", Query.Where.byId(docId = 5))
}
@Test
@DisplayName("Where.byId generates defaults (SQLite)")
fun whereByIdDefaultSQLite() {
Configuration.connectionString = lite
assertEquals("data->>'id' = :id", Query.Where.byId(docId = ""))
}
@Test
@DisplayName("Where.byId generates named ID (PostgreSQL)")
fun whereByIdDefaultNamedPostgres() {
Configuration.connectionString = pg
assertEquals("data->>'id' = :key", Query.Where.byId<String>(":key"))
}
@Test
@DisplayName("Where.byId generates named ID (SQLite)")
fun whereByIdDefaultNamedSQLite() {
Configuration.connectionString = lite
assertEquals("data->>'id' = :key", Query.Where.byId<String>(":key"))
}
// ~~~ Definition ~~~
@Test @Test
@DisplayName("Definition.ensureTableFor generates correctly") @DisplayName("Definition.ensureTableFor generates correctly")
fun ensureTableFor() { fun ensureTableFor() =
assertEquals("CREATE TABLE IF NOT EXISTS my.table (data JSONB NOT NULL)", assertEquals("CREATE TABLE IF NOT EXISTS my.table (data JSONB NOT NULL)",
Query.Definition.ensureTableFor("my.table", "JSONB"), "CREATE TABLE statement not constructed correctly") Query.Definition.ensureTableFor("my.table", "JSONB"), "CREATE TABLE statement not constructed correctly")
}
@Test @Test
@DisplayName("Definition.ensureKey generates correctly with schema") @DisplayName("Definition.ensureKey generates correctly with schema")
fun ensureKeyWithSchema() { fun ensureKeyWithSchema() =
assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data->>'id'))", assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data->>'id'))",
Query.Definition.ensureKey("test.table", Dialect.POSTGRESQL), Query.Definition.ensureKey("test.table", Dialect.POSTGRESQL),
"CREATE INDEX for key statement with schema not constructed correctly") "CREATE INDEX for key statement with schema not constructed correctly")
}
@Test @Test
@DisplayName("Definition.ensureKey generates correctly without schema") @DisplayName("Definition.ensureKey generates correctly without schema")
fun ensureKeyWithoutSchema() { fun ensureKeyWithoutSchema() =
assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_${tbl}_key ON $tbl ((data->>'id'))", assertEquals("CREATE UNIQUE INDEX IF NOT EXISTS idx_${tbl}_key ON $tbl ((data->>'id'))",
Query.Definition.ensureKey(tbl, Dialect.SQLITE), Query.Definition.ensureKey(tbl, Dialect.SQLITE),
"CREATE INDEX for key statement without schema not constructed correctly") "CREATE INDEX for key statement without schema not constructed correctly")
}
@Test @Test
@DisplayName("Definition.ensureIndexOn generates multiple fields and directions") @DisplayName("Definition.ensureIndexOn generates multiple fields and directions")
fun ensureIndexOnMultipleFields() { fun ensureIndexOnMultipleFields() =
assertEquals( assertEquals(
"CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table ((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)", "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"), Query.Definition.ensureIndexOn("test.table", "gibberish", listOf("taco", "guac DESC", "salsa ASC"),
Dialect.POSTGRESQL), Dialect.POSTGRESQL),
"CREATE INDEX for multiple field statement not constructed correctly") "CREATE INDEX for multiple field statement not constructed correctly")
}
@Test @Test
@DisplayName("Definition.ensureIndexOn generates nested PostgreSQL field") @DisplayName("Definition.ensureIndexOn generates nested PostgreSQL field")
fun ensureIndexOnNestedPostgres() { fun ensureIndexOnNestedPostgres() =
assertEquals("CREATE INDEX IF NOT EXISTS idx_${tbl}_nest ON $tbl ((data#>>'{a,b,c}'))", 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), Query.Definition.ensureIndexOn(tbl, "nest", listOf("a.b.c"), Dialect.POSTGRESQL),
"CREATE INDEX for nested PostgreSQL field incorrect") "CREATE INDEX for nested PostgreSQL field incorrect")
}
@Test @Test
@DisplayName("Definition.ensureIndexOn generates nested SQLite field") @DisplayName("Definition.ensureIndexOn generates nested SQLite field")
fun ensureIndexOnNestedSQLite() { fun ensureIndexOnNestedSQLite() =
assertEquals("CREATE INDEX IF NOT EXISTS idx_${tbl}_nest ON $tbl ((data->'a'->'b'->>'c'))", 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), Query.Definition.ensureIndexOn(tbl, "nest", listOf("a.b.c"), Dialect.SQLITE),
"CREATE INDEX for nested SQLite field incorrect") "CREATE INDEX for nested SQLite field incorrect")
}
@Test @Test
@DisplayName("insert generates correctly") @DisplayName("insert generates correctly")
fun insert() { fun insert() {
Configuration.connectionString = ":postgresql:" Configuration.connectionString = pg
assertEquals("INSERT INTO $tbl VALUES (:data)", Query.insert(tbl), "INSERT statement not constructed correctly") assertEquals("INSERT INTO $tbl VALUES (:data)", Query.insert(tbl), "INSERT statement not constructed correctly")
} }
@Test @Test
@DisplayName("save generates correctly") @DisplayName("save generates correctly")
fun save() { fun save() {
Configuration.connectionString = ":postgresql:" Configuration.connectionString = pg
assertEquals( assertEquals(
"INSERT INTO $tbl VALUES (:data) ON CONFLICT ((data->>'id')) DO UPDATE SET data = EXCLUDED.data", "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") Query.save(tbl), "INSERT ON CONFLICT UPDATE statement not constructed correctly")
@ -91,34 +193,29 @@ class QueryTest {
@Test @Test
@DisplayName("count generates correctly") @DisplayName("count generates correctly")
fun count() { fun count() =
assertEquals("SELECT COUNT(*) AS it FROM $tbl", Query.count(tbl), "Count query not constructed correctly") assertEquals("SELECT COUNT(*) AS it FROM $tbl", Query.count(tbl), "Count query not constructed correctly")
}
@Test @Test
@DisplayName("exists generates correctly") @DisplayName("exists generates correctly")
fun exists() { fun exists() =
assertEquals("SELECT EXISTS (SELECT 1 FROM $tbl WHERE turkey) AS it", Query.exists(tbl, "turkey"), assertEquals("SELECT EXISTS (SELECT 1 FROM $tbl WHERE turkey) AS it", Query.exists(tbl, "turkey"),
"Exists query not constructed correctly") "Exists query not constructed correctly")
}
@Test @Test
@DisplayName("find generates correctly") @DisplayName("find generates correctly")
fun find() { fun find() =
assertEquals("SELECT data FROM $tbl", Query.find(tbl), "Find query not constructed correctly") assertEquals("SELECT data FROM $tbl", Query.find(tbl), "Find query not constructed correctly")
}
@Test @Test
@DisplayName("update generates successfully") @DisplayName("update generates successfully")
fun update() { fun update() =
assertEquals("UPDATE $tbl SET data = :data", Query.update(tbl), "Update query not constructed correctly") assertEquals("UPDATE $tbl SET data = :data", Query.update(tbl), "Update query not constructed correctly")
}
@Test @Test
@DisplayName("delete generates successfully") @DisplayName("delete generates successfully")
fun delete() { fun delete() =
assertEquals("DELETE FROM $tbl", Query.delete(tbl), "Delete query not constructed correctly") assertEquals("DELETE FROM $tbl", Query.delete(tbl), "Delete query not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates for no fields") @DisplayName("orderBy generates for no fields")
@ -129,65 +226,57 @@ class QueryTest {
@Test @Test
@DisplayName("orderBy generates single, no direction for PostgreSQL") @DisplayName("orderBy generates single, no direction for PostgreSQL")
fun orderBySinglePostgres() { fun orderBySinglePostgres() =
assertEquals(" ORDER BY data->>'TestField'", assertEquals(" ORDER BY data->>'TestField'",
Query.orderBy(listOf(Field.named("TestField")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly") Query.orderBy(listOf(Field.named("TestField")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates single, no direction for SQLite") @DisplayName("orderBy generates single, no direction for SQLite")
fun orderBySingleSQLite() { fun orderBySingleSQLite() =
assertEquals(" ORDER BY data->>'TestField'", Query.orderBy(listOf(Field.named("TestField")), Dialect.SQLITE), assertEquals(" ORDER BY data->>'TestField'", Query.orderBy(listOf(Field.named("TestField")), Dialect.SQLITE),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates multiple with direction for PostgreSQL") @DisplayName("orderBy generates multiple with direction for PostgreSQL")
fun orderByMultiplePostgres() { fun orderByMultiplePostgres() =
assertEquals(" ORDER BY data#>>'{Nested,Test,Field}' DESC, data->>'AnotherField', data->>'It' DESC", assertEquals(" ORDER BY data#>>'{Nested,Test,Field}' DESC, data->>'AnotherField', data->>'It' DESC",
Query.orderBy( Query.orderBy(
listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")), listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")),
Dialect.POSTGRESQL), Dialect.POSTGRESQL),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates multiple with direction for SQLite") @DisplayName("orderBy generates multiple with direction for SQLite")
fun orderByMultipleSQLite() { fun orderByMultipleSQLite() =
assertEquals(" ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC", assertEquals(" ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC",
Query.orderBy( Query.orderBy(
listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")), listOf(Field.named("Nested.Test.Field DESC"), Field.named("AnotherField"), Field.named("It DESC")),
Dialect.SQLITE), Dialect.SQLITE),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates numeric ordering PostgreSQL") @DisplayName("orderBy generates numeric ordering PostgreSQL")
fun orderByNumericPostgres() { fun orderByNumericPostgres() =
assertEquals(" ORDER BY (data->>'Test')::numeric", assertEquals(" ORDER BY (data->>'Test')::numeric",
Query.orderBy(listOf(Field.named("n:Test")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly") Query.orderBy(listOf(Field.named("n:Test")), Dialect.POSTGRESQL), "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates numeric ordering for SQLite") @DisplayName("orderBy generates numeric ordering for SQLite")
fun orderByNumericSQLite() { fun orderByNumericSQLite() =
assertEquals(" ORDER BY data->>'Test'", Query.orderBy(listOf(Field.named("n:Test")), Dialect.SQLITE), assertEquals(" ORDER BY data->>'Test'", Query.orderBy(listOf(Field.named("n:Test")), Dialect.SQLITE),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates case-insensitive ordering for PostgreSQL") @DisplayName("orderBy generates case-insensitive ordering for PostgreSQL")
fun orderByCIPostgres() { fun orderByCIPostgres() =
assertEquals(" ORDER BY LOWER(data#>>'{Test,Field}') DESC NULLS FIRST", assertEquals(" ORDER BY LOWER(data#>>'{Test,Field}') DESC NULLS FIRST",
Query.orderBy(listOf(Field.named("i:Test.Field DESC NULLS FIRST")), Dialect.POSTGRESQL), Query.orderBy(listOf(Field.named("i:Test.Field DESC NULLS FIRST")), Dialect.POSTGRESQL),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
@Test @Test
@DisplayName("orderBy generates case-insensitive ordering for SQLite") @DisplayName("orderBy generates case-insensitive ordering for SQLite")
fun orderByCISQLite() { fun orderByCISQLite() =
assertEquals(" ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST", assertEquals(" ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST",
Query.orderBy(listOf(Field.named("i:Test.Field ASC NULLS LAST")), Dialect.SQLITE), Query.orderBy(listOf(Field.named("i:Test.Field ASC NULLS LAST")), Dialect.SQLITE),
"ORDER BY not constructed correctly") "ORDER BY not constructed correctly")
}
} }