summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDico Karssiens <dico.karssiens@gmail.com>2018-07-29 12:38:52 +0100
committerDico Karssiens <dico.karssiens@gmail.com>2018-07-29 12:38:52 +0100
commitd043cfae16b0e81be597d8eb5a7a4c1bfa163622 (patch)
treec2372d1e1c388a9fe8b055f7990838b050e51d82
parent015a5f369d140c766ce5d94e3148e799f718aeaf (diff)
Upsert works now
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt4
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt76
2 files changed, 9 insertions, 71 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
index 32371f1..9a26acc 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt
@@ -252,7 +252,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
it[ParcelOptionsT.interact_inventory] = value
}*/
- ParcelOptionsT.replace {
+ ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
it[ParcelOptionsT.parcel_id] = id
it[ParcelOptionsT.interact_inventory] = value
}
@@ -260,7 +260,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource) : Backing
override suspend fun setParcelAllowsInteractInputs(parcel: Parcel, value: Boolean): Unit = transaction {
val id = getOrInitParcelId(parcel)
- ParcelOptionsT.replace {
+ ParcelOptionsT.upsert(ParcelOptionsT.parcel_id) {
it[ParcelOptionsT.parcel_id] = id
it[ParcelOptionsT.interact_inputs] = value
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt
index 30f9b02..7533586 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt
@@ -5,44 +5,11 @@ import org.jetbrains.exposed.sql.statements.InsertStatement
import org.jetbrains.exposed.sql.statements.UpdateStatement
import org.jetbrains.exposed.sql.transactions.TransactionManager
-/*
- * insertOrUpdate from https://github.com/JetBrains/Exposed/issues/167#issuecomment-403837917
- */
-inline fun <T : Table> T.insertOrUpdate(vararg onDuplicateUpdateKeys: Column<*>, body: T.(InsertStatement<Number>) -> Unit) =
- InsertOrUpdate<Number>(onDuplicateUpdateKeys, this).apply {
- body(this)
- execute(TransactionManager.current())
- }
-
-class InsertOrUpdate<Key : Any>(
- private val onDuplicateUpdateKeys: Array<out Column<*>>,
- table: Table,
- isIgnore: Boolean = false
-) : InsertStatement<Key>(table, isIgnore) {
- override fun prepareSQL(transaction: Transaction): String {
- val onUpdateSQL = if (onDuplicateUpdateKeys.isNotEmpty()) {
- " ON DUPLICATE KEY UPDATE " + onDuplicateUpdateKeys.joinToString { "${transaction.identity(it)}=VALUES(${transaction.identity(it)})" }
- } else ""
- return super.prepareSQL(transaction) + onUpdateSQL
- }
-}
-
-
class UpsertStatement<Key : Any>(table: Table, conflictColumn: Column<*>? = null, conflictIndex: Index? = null)
: InsertStatement<Key>(table, false) {
val indexName: String
val indexColumns: List<Column<*>>
- private fun getUpdateStatement(): UpdateStatement {
- val map: Map<Column<Any?>, Any?> = values.castUnchecked()
- val statement = updateBody(table, UpdateStatement(table, null, combineAsConjunctions(indexColumns.castUnchecked(), map))) {
- map.forEach { col, value -> if (col !in indexColumns)
- it[col] = value
- }
- }
- return statement
- }
-
init {
when {
conflictIndex != null -> {
@@ -57,44 +24,15 @@ class UpsertStatement<Key : Any>(table: Table, conflictColumn: Column<*>? = null
}
}
- override fun prepareSQL(transaction: Transaction): String {
- val insertSQL = super.prepareSQL(transaction)
- val updateStatement = getUpdateStatement()
- val updateSQL = updateStatement.prepareSQL(transaction)
- super.arguments = listOf(super.arguments!!.first(), updateStatement.firstDataSet)
-
- return buildString {
- append(insertSQL)
- append(" ON CONFLICT(")
- append(indexName)
- append(") DO UPDATE ")
- append(updateSQL)
- }.also { println(it) }
- }
-
- private companion object {
-
- inline fun <T : Table> updateBody(table: T, updateStatement: UpdateStatement,
- body: T.(UpdateStatement) -> Unit): UpdateStatement {
- table.body(updateStatement)
- return updateStatement
- }
+ override fun prepareSQL(transaction: Transaction) = buildString {
+ append(super.prepareSQL(transaction))
+ append(" ON CONFLICT(")
+ append(indexName)
+ append(") DO UPDATE SET ")
- @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
- inline fun <T> Any.castUnchecked() = this as T
+ values.keys.filter { it !in indexColumns}.joinTo(this) { "${transaction.identity(it)}=EXCLUDED.${transaction.identity(it)}" }
+ }.also { println(it) }
- private val absent = Any() // marker object
- fun combineAsConjunctions(columns: Iterable<Column<Any?>>, map: Map<Column<Any?>, Any?>): Op<Boolean>? {
- return with(SqlExpressionBuilder) {
- columns.fold<Column<Any?>, Op<Boolean>?>(null) { op, col ->
- val arg = map.getOrDefault(col, absent)
- if (arg === absent) return@fold op
- op?.let { it and (col eq arg) } ?: col eq arg
- }
- }
- }
-
- }
}
inline fun <T : Table> T.upsert(conflictColumn: Column<*>? = null, conflictIndex: Index? = null, body: T.(UpsertStatement<Number>) -> Unit) =