From b2d700e6586490250370e570fc013104bfe4d909 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Wed, 26 Feb 2025 23:24:02 -0500 Subject: [PATCH] Move ITs to common files, call from both DBs - Fix PostgreSQL auto-number syntax --- pom.xml | 6 + src/integration-test/kotlin/CustomSQLiteIT.kt | 103 ------------------ .../kotlin/DocumentSQLiteIT.kt | 66 ----------- src/integration-test/kotlin/Types.kt | 3 + src/integration-test/kotlin/common/Custom.kt | 80 ++++++++++++++ .../kotlin/common/Document.kt | 59 ++++++++++ .../kotlin/postgresql/CustomIT.kt | 48 ++++++++ .../kotlin/postgresql/DocumentIT.kt | 27 +++++ .../kotlin/postgresql/PgDB.kt | 53 +++++++++ .../kotlin/sqlite/CustomIT.kt | 47 ++++++++ .../DefinitionIT.kt} | 5 +- .../kotlin/sqlite/DocumentIT.kt | 28 +++++ .../kotlin/{ => sqlite}/SQLiteDB.kt | 5 +- src/main/kotlin/Document.kt | 30 +++-- src/main/kotlin/Parameters.kt | 4 +- 15 files changed, 378 insertions(+), 186 deletions(-) delete mode 100644 src/integration-test/kotlin/CustomSQLiteIT.kt delete mode 100644 src/integration-test/kotlin/DocumentSQLiteIT.kt create mode 100644 src/integration-test/kotlin/common/Custom.kt create mode 100644 src/integration-test/kotlin/common/Document.kt create mode 100644 src/integration-test/kotlin/postgresql/CustomIT.kt create mode 100644 src/integration-test/kotlin/postgresql/DocumentIT.kt create mode 100644 src/integration-test/kotlin/postgresql/PgDB.kt create mode 100644 src/integration-test/kotlin/sqlite/CustomIT.kt rename src/integration-test/kotlin/{DefinitionSQLiteIT.kt => sqlite/DefinitionIT.kt} (94%) create mode 100644 src/integration-test/kotlin/sqlite/DocumentIT.kt rename src/integration-test/kotlin/{ => sqlite}/SQLiteDB.kt (78%) diff --git a/pom.xml b/pom.xml index 3e2ef74..4c36a0f 100644 --- a/pom.xml +++ b/pom.xml @@ -113,6 +113,12 @@ 3.46.1.2 integration-test + + org.postgresql + postgresql + 42.7.5 + integration-test + \ No newline at end of file diff --git a/src/integration-test/kotlin/CustomSQLiteIT.kt b/src/integration-test/kotlin/CustomSQLiteIT.kt deleted file mode 100644 index 1b97baf..0000000 --- a/src/integration-test/kotlin/CustomSQLiteIT.kt +++ /dev/null @@ -1,103 +0,0 @@ -package solutions.bitbadger.documents - -import org.junit.jupiter.api.DisplayName -import solutions.bitbadger.documents.query.Count -import solutions.bitbadger.documents.query.Find -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -/** - * SQLite integration tests for the `Custom` object / `custom*` connection extension functions - */ -@DisplayName("SQLite - Custom") -class CustomSQLiteIT { - - @Test - @DisplayName("list succeeds with empty list") - fun listEmpty() = - SQLiteDB().use { db -> - JsonDocument.load(db.conn, SQLiteDB.tableName) - db.conn.customNonQuery("DELETE FROM ${SQLiteDB.tableName}") - val result = db.conn.customList(Find.all(SQLiteDB.tableName), mapFunc = Results::fromData) - assertEquals(0, result.size, "There should have been no results") - } - - @Test - @DisplayName("list succeeds with a non-empty list") - fun listAll() = - SQLiteDB().use { db -> - JsonDocument.load(db.conn, SQLiteDB.tableName) - val result = db.conn.customList(Find.all(SQLiteDB.tableName), mapFunc = Results::fromData) - assertEquals(5, result.size, "There should have been 5 results") - } - - @Test - @DisplayName("single succeeds when document not found") - fun singleNone() = - SQLiteDB().use { db -> - assertNull( - db.conn.customSingle(Find.all(SQLiteDB.tableName), mapFunc = Results::fromData), - "There should not have been a document returned" - ) - } - - @Test - @DisplayName("single succeeds when a document is found") - fun singleOne() { - SQLiteDB().use { db -> - JsonDocument.load(db.conn, SQLiteDB.tableName) - assertNotNull( - db.conn.customSingle(Find.all(SQLiteDB.tableName), mapFunc = Results::fromData), - "There should not have been a document returned" - ) - } - } - - @Test - @DisplayName("nonQuery makes changes") - fun nonQueryChanges() = - SQLiteDB().use { db -> - JsonDocument.load(db.conn, SQLiteDB.tableName) - assertEquals( - 5L, db.conn.customScalar(Count.all(SQLiteDB.tableName), mapFunc = Results::toCount), - "There should have been 5 documents in the table" - ) - db.conn.customNonQuery("DELETE FROM ${SQLiteDB.tableName}") - assertEquals( - 0L, db.conn.customScalar(Count.all(SQLiteDB.tableName), mapFunc = Results::toCount), - "There should have been no documents in the table" - ) - } - - @Test - @DisplayName("nonQuery makes no changes when where clause matches nothing") - fun nonQueryNoChanges() = - SQLiteDB().use { db -> - JsonDocument.load(db.conn, SQLiteDB.tableName) - assertEquals( - 5L, db.conn.customScalar(Count.all(SQLiteDB.tableName), mapFunc = Results::toCount), - "There should have been 5 documents in the table" - ) - db.conn.customNonQuery( - "DELETE FROM ${SQLiteDB.tableName} WHERE data->>'id' = :id", - listOf(Parameter(":id", ParameterType.STRING, "eighty-two")) - ) - assertEquals( - 5L, db.conn.customScalar(Count.all(SQLiteDB.tableName), mapFunc = Results::toCount), - "There should still have been 5 documents in the table" - ) - } - - @Test - @DisplayName("scalar succeeds") - fun scalar() = - SQLiteDB().use { db -> - assertEquals( - 3L, - db.conn.customScalar("SELECT 3 AS it FROM ${SQLiteDB.catalog} LIMIT 1", mapFunc = Results::toCount), - "The number 3 should have been returned" - ) - } -} diff --git a/src/integration-test/kotlin/DocumentSQLiteIT.kt b/src/integration-test/kotlin/DocumentSQLiteIT.kt deleted file mode 100644 index e4dd09a..0000000 --- a/src/integration-test/kotlin/DocumentSQLiteIT.kt +++ /dev/null @@ -1,66 +0,0 @@ -package solutions.bitbadger.documents - -import org.junit.jupiter.api.DisplayName -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.fail - -/** - * SQLite integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions - */ -@DisplayName("SQLite - Document") -class DocumentSQLiteIT { - - @Test - @DisplayName("insert works with default values") - fun insertDefault() = - SQLiteDB().use { db -> - assertEquals(0L, db.conn.countAll(SQLiteDB.tableName), "There should be no documents in the table") - val doc = JsonDocument("turkey", "", 0, SubDocument("gobble", "gobble")) - db.conn.insert(SQLiteDB.tableName, doc) - val after = db.conn.findAll(SQLiteDB.tableName) - assertEquals(1, after.size, "There should be one document in the table") - assertEquals(doc, after[0], "The document should be what was inserted") - } - - @Test - @DisplayName("insert fails with duplicate key") - fun insertDupe() = - SQLiteDB().use { db -> - db.conn.insert(SQLiteDB.tableName, JsonDocument("a", "", 0, null)) - try { - db.conn.insert(SQLiteDB.tableName, JsonDocument("a", "b", 22, null)) - fail("Inserting a document with a duplicate key should have thrown an exception") - } catch (_: Exception) { - // yay - } - } - - @Test - @DisplayName("insert succeeds with numeric auto IDs") - fun insertNumAutoId() = - SQLiteDB().use { db -> - try { - Configuration.autoIdStrategy = AutoId.NUMBER - Configuration.idField = "key" - assertEquals(0L, db.conn.countAll(SQLiteDB.tableName), "There should be no documents in the table") - - db.conn.insert(SQLiteDB.tableName, NumIdDocument(0, "one")) - db.conn.insert(SQLiteDB.tableName, NumIdDocument(0, "two")) - db.conn.insert(SQLiteDB.tableName, NumIdDocument(77, "three")) - db.conn.insert(SQLiteDB.tableName, NumIdDocument(0, "four")) - - val after = db.conn.findAll(SQLiteDB.tableName, listOf(Field.named("key"))) - assertEquals(4, after.size, "There should have been 4 documents returned") - assertEquals( - "1|2|77|78", after.joinToString("|") { it.key.toString() }, - "The IDs were not generated correctly" - ) - } finally { - Configuration.autoIdStrategy = AutoId.DISABLED - Configuration.idField = "id" - } - } - - // TODO: UUID, Random String -} diff --git a/src/integration-test/kotlin/Types.kt b/src/integration-test/kotlin/Types.kt index a82af38..6b6c595 100644 --- a/src/integration-test/kotlin/Types.kt +++ b/src/integration-test/kotlin/Types.kt @@ -38,3 +38,6 @@ data class JsonDocument(val id: String, val value: String, val numValue: Int, va testDocuments.forEach { conn.insert(tableName, it) } } } + +/** The test table name to use for integration tests */ +val testTableName = "test_table" diff --git a/src/integration-test/kotlin/common/Custom.kt b/src/integration-test/kotlin/common/Custom.kt new file mode 100644 index 0000000..54b7a93 --- /dev/null +++ b/src/integration-test/kotlin/common/Custom.kt @@ -0,0 +1,80 @@ +package solutions.bitbadger.documents.common + +import solutions.bitbadger.documents.* +import solutions.bitbadger.documents.query.Count +import solutions.bitbadger.documents.query.Find +import java.sql.Connection +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull + +/** + * Integration tests for the `Custom` object + */ +object Custom { + + fun listEmpty(conn: Connection) { + JsonDocument.load(conn, testTableName) + conn.customNonQuery("DELETE FROM $testTableName") + val result = conn.customList(Find.all(testTableName), mapFunc = Results::fromData) + assertEquals(0, result.size, "There should have been no results") + } + + fun listAll(conn: Connection) { + JsonDocument.load(conn, testTableName) + val result = conn.customList(Find.all(testTableName), mapFunc = Results::fromData) + assertEquals(5, result.size, "There should have been 5 results") + } + + fun singleNone(conn: Connection) = + assertNull( + conn.customSingle(Find.all(testTableName), mapFunc = Results::fromData), + "There should not have been a document returned" + ) + + fun singleOne(conn: Connection) { + JsonDocument.load(conn, testTableName) + assertNotNull( + conn.customSingle(Find.all(testTableName), mapFunc = Results::fromData), + "There should not have been a document returned" + ) + } + + fun nonQueryChanges(conn: Connection) { + JsonDocument.load(conn, testTableName) + assertEquals( + 5L, conn.customScalar(Count.all(testTableName), mapFunc = Results::toCount), + "There should have been 5 documents in the table" + ) + conn.customNonQuery("DELETE FROM $testTableName") + assertEquals( + 0L, conn.customScalar(Count.all(testTableName), mapFunc = Results::toCount), + "There should have been no documents in the table" + ) + } + + fun nonQueryNoChanges(conn: Connection) { + JsonDocument.load(conn, testTableName) + assertEquals( + 5L, conn.customScalar(Count.all(testTableName), mapFunc = Results::toCount), + "There should have been 5 documents in the table" + ) + conn.customNonQuery( + "DELETE FROM $testTableName WHERE data->>'id' = :id", + listOf(Parameter(":id", ParameterType.STRING, "eighty-two")) + ) + assertEquals( + 5L, conn.customScalar(Count.all(testTableName), mapFunc = Results::toCount), + "There should still have been 5 documents in the table" + ) + } + + fun scalar(conn: Connection) { + JsonDocument.load(conn, testTableName) + assertEquals( + 3L, + conn.customScalar("SELECT 3 AS it FROM $testTableName LIMIT 1", mapFunc = Results::toCount), + "The number 3 should have been returned" + ) + } +} diff --git a/src/integration-test/kotlin/common/Document.kt b/src/integration-test/kotlin/common/Document.kt new file mode 100644 index 0000000..613f831 --- /dev/null +++ b/src/integration-test/kotlin/common/Document.kt @@ -0,0 +1,59 @@ +package solutions.bitbadger.documents.common + +import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.* +import solutions.bitbadger.documents.sqlite.SQLiteDB +import java.sql.Connection +import kotlin.test.assertEquals +import kotlin.test.fail + +/** + * Integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions + */ +object Document { + + fun insertDefault(conn: Connection) { + assertEquals(0L, conn.countAll(testTableName), "There should be no documents in the table") + val doc = JsonDocument("turkey", "", 0, SubDocument("gobble", "gobble")) + conn.insert(testTableName, doc) + val after = conn.findAll(testTableName) + assertEquals(1, after.size, "There should be one document in the table") + assertEquals(doc, after[0], "The document should be what was inserted") + } + + fun insertDupe(conn: Connection) { + conn.insert(testTableName, JsonDocument("a", "", 0, null)) + try { + conn.insert(testTableName, JsonDocument("a", "b", 22, null)) + fail("Inserting a document with a duplicate key should have thrown an exception") + } catch (_: Exception) { + // yay + } + } + + fun insertNumAutoId(conn: Connection) { + try { + Configuration.autoIdStrategy = AutoId.NUMBER + Configuration.idField = "key" + assertEquals(0L, conn.countAll(SQLiteDB.tableName), "There should be no documents in the table") + + conn.insert(SQLiteDB.tableName, NumIdDocument(0, "one")) + conn.insert(SQLiteDB.tableName, NumIdDocument(0, "two")) + conn.insert(SQLiteDB.tableName, NumIdDocument(77, "three")) + conn.insert(SQLiteDB.tableName, NumIdDocument(0, "four")) + + val after = conn.findAll(SQLiteDB.tableName, listOf(Field.named("key"))) + assertEquals(4, after.size, "There should have been 4 documents returned") + assertEquals( + "1|2|77|78", after.joinToString("|") { it.key.toString() }, + "The IDs were not generated correctly" + ) + } finally { + Configuration.autoIdStrategy = AutoId.DISABLED + Configuration.idField = "id" + } + } + + // TODO: UUID, Random String + +} \ No newline at end of file diff --git a/src/integration-test/kotlin/postgresql/CustomIT.kt b/src/integration-test/kotlin/postgresql/CustomIT.kt new file mode 100644 index 0000000..d356e57 --- /dev/null +++ b/src/integration-test/kotlin/postgresql/CustomIT.kt @@ -0,0 +1,48 @@ +package solutions.bitbadger.documents.postgresql + +import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.common.Custom + +import kotlin.test.Test + +/** + * PostgreSQL integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("PostgreSQL - Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + fun listEmpty() = + PgDB().use { Custom.listEmpty(it.conn) } + + @Test + @DisplayName("list succeeds with a non-empty list") + fun listAll() = + PgDB().use { Custom.listAll(it.conn) } + + @Test + @DisplayName("single succeeds when document not found") + fun singleNone() = + PgDB().use { Custom.singleNone(it.conn) } + + @Test + @DisplayName("single succeeds when a document is found") + fun singleOne() = + PgDB().use { Custom.singleOne(it.conn) } + + @Test + @DisplayName("nonQuery makes changes") + fun nonQueryChanges() = + PgDB().use { Custom.nonQueryChanges(it.conn) } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + fun nonQueryNoChanges() = + PgDB().use { Custom.nonQueryNoChanges(it.conn) } + + @Test + @DisplayName("scalar succeeds") + fun scalar() = + PgDB().use { Custom.scalar(it.conn) } +} diff --git a/src/integration-test/kotlin/postgresql/DocumentIT.kt b/src/integration-test/kotlin/postgresql/DocumentIT.kt new file mode 100644 index 0000000..003b23d --- /dev/null +++ b/src/integration-test/kotlin/postgresql/DocumentIT.kt @@ -0,0 +1,27 @@ +package solutions.bitbadger.documents.postgresql + +import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.common.Document +import kotlin.test.Test + +/** + * PostgreSQL integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions + */ +@DisplayName("PostgreSQL - Document") +class DocumentIT { + + @Test + @DisplayName("insert works with default values") + fun insertDefault() = + PgDB().use { Document.insertDefault(it.conn) } + + @Test + @DisplayName("insert fails with duplicate key") + fun insertDupe() = + PgDB().use { Document.insertDupe(it.conn) } + + @Test + @DisplayName("insert succeeds with numeric auto IDs") + fun insertNumAutoId() = + PgDB().use { Document.insertNumAutoId(it.conn) } +} diff --git a/src/integration-test/kotlin/postgresql/PgDB.kt b/src/integration-test/kotlin/postgresql/PgDB.kt new file mode 100644 index 0000000..cfc4da3 --- /dev/null +++ b/src/integration-test/kotlin/postgresql/PgDB.kt @@ -0,0 +1,53 @@ +package solutions.bitbadger.documents.postgresql + +import solutions.bitbadger.documents.AutoId +import solutions.bitbadger.documents.Configuration +import solutions.bitbadger.documents.customNonQuery +import solutions.bitbadger.documents.ensureTable + +/** + * A wrapper for a throwaway PostgreSQL database + */ +class PgDB : AutoCloseable { + + private var dbName = "" + + init { + dbName = "throwaway_${AutoId.generateRandomString(8)}" + Configuration.connectionString = connString("postgres") + Configuration.dbConn().use { + it.customNonQuery("CREATE DATABASE $dbName") + } + Configuration.connectionString = connString(dbName) + } + + val conn = Configuration.dbConn() + + init { + conn.ensureTable(tableName) + } + + override fun close() { + conn.close() + Configuration.connectionString = connString("postgres") + Configuration.dbConn().use { + it.customNonQuery("DROP DATABASE $dbName") + } + Configuration.connectionString = null + } + + companion object { + + /** The table used for test documents */ + val tableName = "test_table" + + /** + * Create a connection string for the given database + * + * @param database The database to which the library should connect + * @return The connection string for the database + */ + private fun connString(database: String) = + "jdbc:postgresql://localhost/$database?user=postgres&password=postgres" + } +} diff --git a/src/integration-test/kotlin/sqlite/CustomIT.kt b/src/integration-test/kotlin/sqlite/CustomIT.kt new file mode 100644 index 0000000..723376b --- /dev/null +++ b/src/integration-test/kotlin/sqlite/CustomIT.kt @@ -0,0 +1,47 @@ +package solutions.bitbadger.documents.sqlite + +import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.common.Custom +import kotlin.test.Test + +/** + * SQLite integration tests for the `Custom` object / `custom*` connection extension functions + */ +@DisplayName("SQLite - Custom") +class CustomIT { + + @Test + @DisplayName("list succeeds with empty list") + fun listEmpty() = + SQLiteDB().use { Custom.listEmpty(it.conn) } + + @Test + @DisplayName("list succeeds with a non-empty list") + fun listAll() = + SQLiteDB().use { Custom.listAll(it.conn) } + + @Test + @DisplayName("single succeeds when document not found") + fun singleNone() = + SQLiteDB().use { Custom.singleNone(it.conn) } + + @Test + @DisplayName("single succeeds when a document is found") + fun singleOne() = + SQLiteDB().use { Custom.singleOne(it.conn) } + + @Test + @DisplayName("nonQuery makes changes") + fun nonQueryChanges() = + SQLiteDB().use { Custom.nonQueryChanges(it.conn) } + + @Test + @DisplayName("nonQuery makes no changes when where clause matches nothing") + fun nonQueryNoChanges() = + SQLiteDB().use { Custom.nonQueryNoChanges(it.conn) } + + @Test + @DisplayName("scalar succeeds") + fun scalar() = + SQLiteDB().use { Custom.scalar(it.conn) } +} diff --git a/src/integration-test/kotlin/DefinitionSQLiteIT.kt b/src/integration-test/kotlin/sqlite/DefinitionIT.kt similarity index 94% rename from src/integration-test/kotlin/DefinitionSQLiteIT.kt rename to src/integration-test/kotlin/sqlite/DefinitionIT.kt index 4e27ffd..4e85357 100644 --- a/src/integration-test/kotlin/DefinitionSQLiteIT.kt +++ b/src/integration-test/kotlin/sqlite/DefinitionIT.kt @@ -1,6 +1,7 @@ -package solutions.bitbadger.documents +package solutions.bitbadger.documents.sqlite import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.* import java.sql.Connection import kotlin.test.Test import kotlin.test.assertFalse @@ -10,7 +11,7 @@ import kotlin.test.assertTrue * SQLite integration tests for the `Definition` object / `ensure*` connection extension functions */ @DisplayName("SQLite - Definition") -class DefinitionSQLiteIT { +class DefinitionIT { /** * Determine if a database item exists diff --git a/src/integration-test/kotlin/sqlite/DocumentIT.kt b/src/integration-test/kotlin/sqlite/DocumentIT.kt new file mode 100644 index 0000000..e2a7d98 --- /dev/null +++ b/src/integration-test/kotlin/sqlite/DocumentIT.kt @@ -0,0 +1,28 @@ +package solutions.bitbadger.documents.sqlite + +import org.junit.jupiter.api.DisplayName +import solutions.bitbadger.documents.common.Document +import kotlin.test.Test + +/** + * SQLite integration tests for the `Document` object / `insert`, `save`, `update` connection extension functions + */ +@DisplayName("SQLite - Document") +class DocumentIT { + + @Test + @DisplayName("insert works with default values") + fun insertDefault() = + SQLiteDB().use { Document.insertDefault(it.conn) } + + @Test + @DisplayName("insert fails with duplicate key") + fun insertDupe() = + SQLiteDB().use { Document.insertDupe(it.conn) } + + @Test + @DisplayName("insert succeeds with numeric auto IDs") + fun insertNumAutoId() = + SQLiteDB().use { Document.insertNumAutoId(it.conn) } + +} diff --git a/src/integration-test/kotlin/SQLiteDB.kt b/src/integration-test/kotlin/sqlite/SQLiteDB.kt similarity index 78% rename from src/integration-test/kotlin/SQLiteDB.kt rename to src/integration-test/kotlin/sqlite/SQLiteDB.kt index 2f0118a..db500a9 100644 --- a/src/integration-test/kotlin/SQLiteDB.kt +++ b/src/integration-test/kotlin/sqlite/SQLiteDB.kt @@ -1,5 +1,8 @@ -package solutions.bitbadger.documents +package solutions.bitbadger.documents.sqlite +import solutions.bitbadger.documents.AutoId +import solutions.bitbadger.documents.Configuration +import solutions.bitbadger.documents.ensureTable import java.io.File /** diff --git a/src/main/kotlin/Document.kt b/src/main/kotlin/Document.kt index 1b6ab3f..0f21a75 100644 --- a/src/main/kotlin/Document.kt +++ b/src/main/kotlin/Document.kt @@ -20,19 +20,25 @@ object Document { val query = if (strategy == AutoId.DISABLED) { Document.insert(tableName) } else { - val idField = Configuration.idField - val dialect = Configuration.dialect("Create auto-ID insert query") + val idField = Configuration.idField + val dialect = Configuration.dialect("Create auto-ID insert query") val dataParam = if (AutoId.needsAutoId(strategy, document, idField)) { - when (strategy) { - AutoId.NUMBER -> "(SELECT coalesce(max(data->>'$idField'), 0) + 1 FROM $tableName)" - AutoId.UUID -> "'${AutoId.generateUUID()}'" - AutoId.RANDOM_STRING -> "'${AutoId.generateRandomString()}'" - else -> "(:data)->>'$idField'" - }.let { - when (dialect) { - Dialect.POSTGRESQL -> ":data::jsonb || ('{\"$idField\":$it}')::jsonb" - Dialect.SQLITE -> "json_set(:data, '$.$idField', $it)" - } + when (dialect) { + Dialect.POSTGRESQL -> + when (strategy) { + AutoId.NUMBER -> "' || (SELECT coalesce(max(data->>'$idField')::numeric, 0) + 1 FROM $tableName) || '" + AutoId.UUID -> "\"${AutoId.generateUUID()}\"" + AutoId.RANDOM_STRING -> "\"${AutoId.generateRandomString()}\"" + else -> "\"' || (:data)->>'$idField' || '\"" + }.let { ":data::jsonb || ('{\"$idField\":$it}')::jsonb" } + + Dialect.SQLITE -> + when (strategy) { + AutoId.NUMBER -> "(SELECT coalesce(max(data->>'$idField'), 0) + 1 FROM $tableName)" + AutoId.UUID -> "'${AutoId.generateUUID()}'" + AutoId.RANDOM_STRING -> "'${AutoId.generateRandomString()}'" + else -> "(:data)->>'$idField'" + }.let { "json_set(:data, '$.$idField', $it)" } } } else { ":data" diff --git a/src/main/kotlin/Parameters.kt b/src/main/kotlin/Parameters.kt index 912e9f8..2f8466c 100644 --- a/src/main/kotlin/Parameters.kt +++ b/src/main/kotlin/Parameters.kt @@ -47,7 +47,7 @@ object Parameters { * @return The query, with name parameters changed to `?`s */ fun replaceNamesInQuery(query: String, parameters: Collection>) = - 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 @@ -103,7 +103,7 @@ object Parameters { } } - ParameterType.JSON -> stmt.setString(idx, param.value as String) + ParameterType.JSON -> stmt.setObject(idx, param.value as String, Types.OTHER) } } }