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 224 additions and 4 deletions
Showing only changes of commit bc3b4bb012 - Show all commits

View File

@ -0,0 +1,66 @@
package solutions.bitbadger.documents.common
import solutions.bitbadger.documents.*
import kotlin.test.assertEquals
/**
* Integration tests for the `Delete` object
*/
object Delete {
fun byIdMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteById(TEST_TABLE, "four")
assertEquals(4, db.conn.countAll(TEST_TABLE), "There should now be 4 documents in the table")
}
fun byIdNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteById(TEST_TABLE, "negative four")
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
}
fun byFieldsMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByFields(TEST_TABLE, listOf(Field.notEqual("value", "purple")))
assertEquals(2, db.conn.countAll(TEST_TABLE), "There should now be 2 documents in the table")
}
fun byFieldsNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByFields(TEST_TABLE, listOf(Field.equal("value", "crimson")))
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
}
fun byContainsMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByContains(TEST_TABLE, mapOf("value" to "purple"))
assertEquals(3, db.conn.countAll(TEST_TABLE), "There should now be 3 documents in the table")
}
fun byContainsNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByContains(TEST_TABLE, mapOf("target" to "acquired"))
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
}
fun byJsonPathMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByJsonPath(TEST_TABLE, "$.value ? (@ == \"purple\")")
assertEquals(3, db.conn.countAll(TEST_TABLE), "There should now be 3 documents in the table")
}
fun byJsonPathNoMatch(db: ThrowawayDatabase) {
JsonDocument.load(db)
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should be 5 documents in the table")
db.conn.deleteByJsonPath(TEST_TABLE, "$.numValue ? (@ > 100)")
assertEquals(5, db.conn.countAll(TEST_TABLE), "There should still be 5 documents in the table")
}
}

View File

@ -0,0 +1,49 @@
package solutions.bitbadger.documents.postgresql
import org.junit.jupiter.api.DisplayName
import solutions.bitbadger.documents.common.Delete
import kotlin.test.Test
@DisplayName("PostgreSQL - Delete")
class DeleteIT {
@Test
@DisplayName("byId deletes a matching ID")
fun byIdMatch() =
PgDB().use(Delete::byIdMatch)
@Test
@DisplayName("byId succeeds when no ID matches")
fun byIdNoMatch() =
PgDB().use(Delete::byIdNoMatch)
@Test
@DisplayName("byFields deletes matching documents")
fun byFieldsMatch() =
PgDB().use(Delete::byFieldsMatch)
@Test
@DisplayName("byFields succeeds when no documents match")
fun byFieldsNoMatch() =
PgDB().use(Delete::byFieldsNoMatch)
@Test
@DisplayName("byContains deletes matching documents")
fun byContainsMatch() =
PgDB().use(Delete::byContainsMatch)
@Test
@DisplayName("byContains succeeds when no documents match")
fun byContainsNoMatch() =
PgDB().use(Delete::byContainsNoMatch)
@Test
@DisplayName("byJsonPath deletes matching documents")
fun byJsonPathMatch() =
PgDB().use(Delete::byJsonPathMatch)
@Test
@DisplayName("byJsonPath succeeds when no documents match")
fun byJsonPathNoMatch() =
PgDB().use(Delete::byJsonPathNoMatch)
}

View File

@ -0,0 +1,43 @@
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.Delete
import kotlin.test.Test
@DisplayName("SQLite - Delete")
class DeleteIT {
@Test
@DisplayName("byId deletes a matching ID")
fun byIdMatch() =
SQLiteDB().use(Delete::byIdMatch)
@Test
@DisplayName("byId succeeds when no ID matches")
fun byIdNoMatch() =
SQLiteDB().use(Delete::byIdNoMatch)
@Test
@DisplayName("byFields deletes matching documents")
fun byFieldsMatch() =
SQLiteDB().use(Delete::byFieldsMatch)
@Test
@DisplayName("byFields succeeds when no documents match")
fun byFieldsNoMatch() =
SQLiteDB().use(Delete::byFieldsNoMatch)
@Test
@DisplayName("byContains fails")
fun byContainsMatch() {
assertThrows<DocumentException> { SQLiteDB().use(Delete::byContainsMatch) }
}
@Test
@DisplayName("byJsonPath fails")
fun byJsonPathMatch() {
assertThrows<DocumentException> { SQLiteDB().use(Delete::byJsonPathMatch) }
}
}

View File

@ -165,7 +165,7 @@ inline fun <reified TDoc> Connection.findAll(tableName: String, orderBy: Collect
* @param tableName The name of the table from which documents should be deleted
* @param docId The ID of the document to be deleted
*/
fun <TKey> Connection.byId(tableName: String, docId: TKey) =
fun <TKey> Connection.deleteById(tableName: String, docId: TKey) =
Delete.byId(tableName, docId, this)
/**
@ -177,3 +177,23 @@ fun <TKey> Connection.byId(tableName: String, docId: TKey) =
*/
fun Connection.deleteByFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
Delete.byFields(tableName, fields, howMatched, this)
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param criteria The object for which JSON containment should be checked
* @throws DocumentException If called on a SQLite connection
*/
inline fun <reified T> Connection.deleteByContains(tableName: String, criteria: T) =
Delete.byContains(tableName, criteria, this)
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param path The JSON path comparison to match
* @throws DocumentException If called on a SQLite connection
*/
fun Connection.deleteByJsonPath(tableName: String, path: String) =
Delete.byJsonPath(tableName, path, this)

View File

@ -66,7 +66,7 @@ object Count {
*
* @param tableName The name of the table in which documents should be counted
* @param criteria The object for which JSON containment should be checked
* @param conn The connection on which the deletion should be executed
* @param conn The connection on which the count should be executed
* @return A count of the matching documents in the table
* @throws DocumentException If called on a SQLite connection
*/
@ -89,7 +89,7 @@ object Count {
*
* @param tableName The name of the table in which documents should be counted
* @param path The JSON path comparison to match
* @param conn The connection on which the deletion should be executed
* @param conn The connection on which the count should be executed
* @return A count of the matching documents in the table
* @throws DocumentException If called on a SQLite connection
*/

View File

@ -18,7 +18,7 @@ object Delete {
fun <TKey> byId(tableName: String, docId: TKey, conn: Connection) =
conn.customNonQuery(
Delete.byId(tableName, docId),
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId)))
Parameters.addFields(listOf(Field.equal(Configuration.idField, docId, ":id")))
)
/**
@ -52,4 +52,46 @@ object Delete {
*/
fun byFields(tableName: String, fields: Collection<Field<*>>, howMatched: FieldMatch? = null) =
Configuration.dbConn().use { byFields(tableName, fields, howMatched, it) }
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param criteria The object for which JSON containment should be checked
* @param conn The connection on which the deletion should be executed
* @throws DocumentException If called on a SQLite connection
*/
inline fun <reified T> byContains(tableName: String, criteria: T, conn: Connection) =
conn.customNonQuery(Delete.byContains(tableName), listOf(Parameters.json(":criteria", criteria)))
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param criteria The object for which JSON containment should be checked
* @throws DocumentException If called on a SQLite connection
*/
inline fun <reified T> byContains(tableName: String, criteria: T) =
Configuration.dbConn().use { byContains(tableName, criteria, it) }
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param path The JSON path comparison to match
* @param conn The connection on which the deletion should be executed
* @throws DocumentException If called on a SQLite connection
*/
fun byJsonPath(tableName: String, path: String, conn: Connection) =
conn.customNonQuery(Delete.byJsonPath(tableName), listOf(Parameter(":path", ParameterType.STRING, path)))
/**
* Delete documents using a JSON containment query (PostgreSQL only)
*
* @param tableName The name of the table from which documents should be deleted
* @param path The JSON path comparison to match
* @throws DocumentException If called on a SQLite connection
*/
fun byJsonPath(tableName: String, path: String) =
Configuration.dbConn().use { byJsonPath(tableName, path, it) }
}