Initial Development #1
63
src/integration-test/kotlin/common/Exists.kt
Normal file
63
src/integration-test/kotlin/common/Exists.kt
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package solutions.bitbadger.documents.common
|
||||||
|
|
||||||
|
import solutions.bitbadger.documents.*
|
||||||
|
import kotlin.test.assertFalse
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for the `Exists` object
|
||||||
|
*/
|
||||||
|
object Exists {
|
||||||
|
|
||||||
|
fun byIdMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertTrue("The document with ID \"three\" should exist") { db.conn.existsById(TEST_TABLE, "three") }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byIdNoMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertFalse("The document with ID \"seven\" should not exist") { db.conn.existsById(TEST_TABLE, "seven") }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byFieldsMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertTrue("Matching documents should have been found") {
|
||||||
|
db.conn.existsByFields(TEST_TABLE, listOf(Field.equal("numValue", 10)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byFieldsNoMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertFalse("No matching documents should have been found") {
|
||||||
|
db.conn.existsByFields(TEST_TABLE, listOf(Field.equal("nothing", "none")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byContainsMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertTrue("Matching documents should have been found") {
|
||||||
|
db.conn.existsByContains(TEST_TABLE, mapOf("value" to "purple"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byContainsNoMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertFalse("Matching documents should not have been found") {
|
||||||
|
db.conn.existsByContains(TEST_TABLE, mapOf("value" to "violet"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byJsonPathMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertTrue("Matching documents should have been found") {
|
||||||
|
db.conn.existsByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
|
||||||
|
JsonDocument.load(db)
|
||||||
|
assertFalse("Matching documents should not have been found") {
|
||||||
|
db.conn.existsByJsonPath(TEST_TABLE, "$.numValue ? (@ == 10.1)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,9 @@ import org.junit.jupiter.api.DisplayName
|
|||||||
import solutions.bitbadger.documents.common.Delete
|
import solutions.bitbadger.documents.common.Delete
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostgreSQL integration tests for the `Delete` object / `deleteBy*` connection extension functions
|
||||||
|
*/
|
||||||
@DisplayName("PostgreSQL - Delete")
|
@DisplayName("PostgreSQL - Delete")
|
||||||
class DeleteIT {
|
class DeleteIT {
|
||||||
|
|
||||||
|
52
src/integration-test/kotlin/postgresql/ExistsIT.kt
Normal file
52
src/integration-test/kotlin/postgresql/ExistsIT.kt
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package solutions.bitbadger.documents.postgresql
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import solutions.bitbadger.documents.common.Exists
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostgreSQL integration tests for the `Exists` object / `existsBy*` connection extension functions
|
||||||
|
*/
|
||||||
|
@DisplayName("PostgreSQL - Exists")
|
||||||
|
class ExistsIT {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byId returns true when a document matches the ID")
|
||||||
|
fun byIdMatch() =
|
||||||
|
PgDB().use(Exists::byIdMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byId returns false when no document matches the ID")
|
||||||
|
fun byIdNoMatch() =
|
||||||
|
PgDB().use(Exists::byIdNoMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byFields returns true when documents match")
|
||||||
|
fun byFieldsMatch() =
|
||||||
|
PgDB().use(Exists::byFieldsMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byFields returns false when no documents match")
|
||||||
|
fun byFieldsNoMatch() =
|
||||||
|
PgDB().use(Exists::byFieldsNoMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byContains returns true when documents match")
|
||||||
|
fun byContainsMatch() =
|
||||||
|
PgDB().use(Exists::byContainsMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byContains returns false when no documents match")
|
||||||
|
fun byContainsNoMatch() =
|
||||||
|
PgDB().use(Exists::byContainsNoMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byJsonPath returns true when documents match")
|
||||||
|
fun byJsonPathMatch() =
|
||||||
|
PgDB().use(Exists::byJsonPathMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byJsonPath returns false when no documents match")
|
||||||
|
fun byJsonPathNoMatch() =
|
||||||
|
PgDB().use(Exists::byJsonPathNoMatch)
|
||||||
|
}
|
@ -6,6 +6,9 @@ import solutions.bitbadger.documents.DocumentException
|
|||||||
import solutions.bitbadger.documents.common.Delete
|
import solutions.bitbadger.documents.common.Delete
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQLite integration tests for the `Delete` object / `deleteBy*` connection extension functions
|
||||||
|
*/
|
||||||
@DisplayName("SQLite - Delete")
|
@DisplayName("SQLite - Delete")
|
||||||
class DeleteIT {
|
class DeleteIT {
|
||||||
|
|
||||||
@ -31,13 +34,13 @@ class DeleteIT {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("byContains fails")
|
@DisplayName("byContains fails")
|
||||||
fun byContainsMatch() {
|
fun byContainsFails() {
|
||||||
assertThrows<DocumentException> { SQLiteDB().use(Delete::byContainsMatch) }
|
assertThrows<DocumentException> { SQLiteDB().use(Delete::byContainsMatch) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("byJsonPath fails")
|
@DisplayName("byJsonPath fails")
|
||||||
fun byJsonPathMatch() {
|
fun byJsonPathFails() {
|
||||||
assertThrows<DocumentException> { SQLiteDB().use(Delete::byJsonPathMatch) }
|
assertThrows<DocumentException> { SQLiteDB().use(Delete::byJsonPathMatch) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
src/integration-test/kotlin/sqlite/ExistsIT.kt
Normal file
46
src/integration-test/kotlin/sqlite/ExistsIT.kt
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package solutions.bitbadger.documents.sqlite
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import solutions.bitbadger.documents.DocumentException
|
||||||
|
import solutions.bitbadger.documents.common.Exists
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SQLite integration tests for the `Exists` object / `existsBy*` connection extension functions
|
||||||
|
*/
|
||||||
|
@DisplayName("SQLite - Exists")
|
||||||
|
class ExistsIT {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byId returns true when a document matches the ID")
|
||||||
|
fun byIdMatch() =
|
||||||
|
SQLiteDB().use(Exists::byIdMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byId returns false when no document matches the ID")
|
||||||
|
fun byIdNoMatch() =
|
||||||
|
SQLiteDB().use(Exists::byIdNoMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byFields returns true when documents match")
|
||||||
|
fun byFieldsMatch() =
|
||||||
|
SQLiteDB().use(Exists::byFieldsMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byFields returns false when no documents match")
|
||||||
|
fun byFieldsNoMatch() =
|
||||||
|
SQLiteDB().use(Exists::byFieldsNoMatch)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byContains fails")
|
||||||
|
fun byContainsFails() {
|
||||||
|
assertThrows<DocumentException> { SQLiteDB().use(Exists::byContainsMatch) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("byJsonPath fails")
|
||||||
|
fun byJsonPathFails() {
|
||||||
|
assertThrows<DocumentException> { SQLiteDB().use(Exists::byJsonPathMatch) }
|
||||||
|
}
|
||||||
|
}
|
@ -127,7 +127,7 @@ inline fun <reified T> Connection.countByContains(tableName: String, criteria: T
|
|||||||
Count.byContains(tableName, criteria, this)
|
Count.byContains(tableName, criteria, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count documents using a JSON containment query (PostgreSQL only)
|
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table in which documents should be counted
|
* @param tableName The name of the table in which documents should be counted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
@ -137,6 +137,51 @@ inline fun <reified T> Connection.countByContains(tableName: String, criteria: T
|
|||||||
fun Connection.countByJsonPath(tableName: String, path: String) =
|
fun Connection.countByJsonPath(tableName: String, path: String) =
|
||||||
Count.byJsonPath(tableName, path, this)
|
Count.byJsonPath(tableName, path, this)
|
||||||
|
|
||||||
|
// ~~~ DOCUMENT EXISTENCE QUERIES ~~~
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine a document's existence by its ID
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param docId The ID of the document to be checked
|
||||||
|
* @return True if the document exists, false if not
|
||||||
|
*/
|
||||||
|
fun <TKey> Connection.existsById(tableName: String, docId: TKey) =
|
||||||
|
Exists.byId(tableName, docId, this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a field comparison
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param fields The fields which should be compared
|
||||||
|
* @param howMatched How the fields should be matched
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
*/
|
||||||
|
fun Connection.existsByFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||||
|
Exists.byFields(tableName, fields, howMatched, this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param criteria The object for which JSON containment should be checked
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
inline fun <reified T> Connection.existsByContains(tableName: String, criteria: T) =
|
||||||
|
Exists.byContains(tableName, criteria, this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param path The JSON path comparison to match
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
fun Connection.existsByJsonPath(tableName: String, path: String) =
|
||||||
|
Exists.byJsonPath(tableName, path, this)
|
||||||
|
|
||||||
// ~~~ DOCUMENT RETRIEVAL QUERIES ~~~
|
// ~~~ DOCUMENT RETRIEVAL QUERIES ~~~
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,7 +234,7 @@ inline fun <reified T> Connection.deleteByContains(tableName: String, criteria:
|
|||||||
Delete.byContains(tableName, criteria, this)
|
Delete.byContains(tableName, criteria, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table from which documents should be deleted
|
* @param tableName The name of the table from which documents should be deleted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
|
@ -85,7 +85,7 @@ object Count {
|
|||||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count documents using a JSON containment query (PostgreSQL only)
|
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table in which documents should be counted
|
* @param tableName The name of the table in which documents should be counted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
@ -101,7 +101,7 @@ object Count {
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count documents using a JSON containment query (PostgreSQL only)
|
* Count documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table in which documents should be counted
|
* @param tableName The name of the table in which documents should be counted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
|
@ -75,7 +75,7 @@ object Delete {
|
|||||||
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table from which documents should be deleted
|
* @param tableName The name of the table from which documents should be deleted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
@ -86,7 +86,7 @@ object Delete {
|
|||||||
conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path)))
|
conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete documents using a JSON containment query (PostgreSQL only)
|
* Delete documents using a JSON Path match query (PostgreSQL only)
|
||||||
*
|
*
|
||||||
* @param tableName The name of the table from which documents should be deleted
|
* @param tableName The name of the table from which documents should be deleted
|
||||||
* @param path The JSON path comparison to match
|
* @param path The JSON path comparison to match
|
||||||
|
123
src/main/kotlin/Exists.kt
Normal file
123
src/main/kotlin/Exists.kt
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package solutions.bitbadger.documents
|
||||||
|
|
||||||
|
import solutions.bitbadger.documents.query.Exists
|
||||||
|
import java.sql.Connection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions to determine whether documents exist
|
||||||
|
*/
|
||||||
|
object Exists {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine a document's existence by its ID
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param docId The ID of the document to be checked
|
||||||
|
* @param conn The connection on which the existence check should be executed
|
||||||
|
* @return True if the document exists, false if not
|
||||||
|
*/
|
||||||
|
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
|
||||||
|
conn.customScalar(
|
||||||
|
Exists.byId(tableName, docId),
|
||||||
|
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id"))),
|
||||||
|
Results::toExists
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine a document's existence by its ID
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param docId The ID of the document to be checked
|
||||||
|
* @return True if the document exists, false if not
|
||||||
|
*/
|
||||||
|
fun <TKey> byId(tableName: String, docId: TKey) =
|
||||||
|
Configuration.dbConn().use { byId(tableName, docId, it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a field comparison
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param fields The fields which should be compared
|
||||||
|
* @param howMatched How the fields should be matched
|
||||||
|
* @param conn The connection on which the existence check should be executed
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
*/
|
||||||
|
fun byFields(
|
||||||
|
tableName: String,
|
||||||
|
fields: Collection<Field<*>>,
|
||||||
|
howMatched: FieldMatch? = null,
|
||||||
|
conn: Connection
|
||||||
|
): Boolean {
|
||||||
|
val named = Parameters.nameFields(fields)
|
||||||
|
return conn.customScalar(
|
||||||
|
Exists.byFields(tableName, named, howMatched),
|
||||||
|
Parameters.addFields(named),
|
||||||
|
Results::toExists
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a field comparison
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param fields The fields which should be compared
|
||||||
|
* @param howMatched How the fields should be matched
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
*/
|
||||||
|
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
|
||||||
|
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param criteria The object for which JSON containment should be checked
|
||||||
|
* @param conn The connection on which the existence check should be executed
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
inline fun <reified T> byContains(tableName: String, criteria: T, conn: Connection) =
|
||||||
|
conn.customScalar(
|
||||||
|
Exists.byContains(tableName),
|
||||||
|
listOf(Parameters.json(":criteria", criteria)),
|
||||||
|
Results::toExists
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON containment query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param criteria The object for which JSON containment should be checked
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
inline fun <reified T> byContains(tableName: String, criteria: T) =
|
||||||
|
Configuration.dbConn().use { byContains(tableName, criteria, it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param path The JSON path comparison to match
|
||||||
|
* @param conn The connection on which the existence check should be executed
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
fun byJsonPath(tableName: String, path: String, conn: Connection) =
|
||||||
|
conn.customScalar(
|
||||||
|
Exists.byJsonPath(tableName),
|
||||||
|
listOf(Parameter(":path", ParameterType.STRING, path)),
|
||||||
|
Results::toExists
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine document existence using a JSON Path match query (PostgreSQL only)
|
||||||
|
*
|
||||||
|
* @param tableName The name of the table in which document existence should be checked
|
||||||
|
* @param path The JSON path comparison to match
|
||||||
|
* @return True if any matching documents exist, false if not
|
||||||
|
* @throws DocumentException If called on a SQLite connection
|
||||||
|
*/
|
||||||
|
fun byJsonPath(tableName: String, path: String) =
|
||||||
|
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user