diff options
author | Dico Karssiens <dico.karssiens@gmail.com> | 2018-07-29 12:38:52 +0100 |
---|---|---|
committer | Dico Karssiens <dico.karssiens@gmail.com> | 2018-07-29 12:38:52 +0100 |
commit | d043cfae16b0e81be597d8eb5a7a4c1bfa163622 (patch) | |
tree | c2372d1e1c388a9fe8b055f7990838b050e51d82 | |
parent | 015a5f369d140c766ce5d94e3148e799f718aeaf (diff) |
Upsert works now
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/storage/ExposedBacking.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/storage/ExposedExtensions.kt | 76 |
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) = |