mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2024-12-20 07:37:15 +00:00
changes in insert/update exposed methods and rewriting of read keyvalue(s) exposed repos to be extending abstract key value(s) repos
This commit is contained in:
parent
1107b7f4ef
commit
1257492f85
@ -2,6 +2,15 @@
|
||||
|
||||
## 0.13.0
|
||||
|
||||
* `Repos`:
|
||||
* `Exposed`:
|
||||
* `AbstractExposedWriteCRUDRepo` got two new methods: `update` with `it` as `UpdateBuilder<Int>` and `createAndInsertId`
|
||||
* Old `update` method has been deprecated and not recommended to override anymore in realizations
|
||||
* Old `insert` method now is `open` instead of `abstract` and can be omitted
|
||||
* `AbstractExposedKeyValueRepo` got two new methods: `update` with `it` as `UpdateBuilder<Int>` and `insertKey`
|
||||
* Old `update` method has been deprecated and not recommended to override anymore
|
||||
* Old `insert` method now is `open` instead of `abstract` and can be omitted in realizations
|
||||
|
||||
## 0.12.17
|
||||
|
||||
* `Versions`:
|
||||
|
@ -4,9 +4,9 @@ import dev.inmo.micro_utils.repos.UpdatedValuePair
|
||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import java.util.Objects
|
||||
|
||||
abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
flowsChannelsSize: Int = 0,
|
||||
@ -27,10 +27,31 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
|
||||
protected abstract fun InsertStatement<Number>.asObject(value: InputValueType): ObjectType
|
||||
|
||||
protected abstract fun insert(value: InputValueType, it: InsertStatement<Number>)
|
||||
protected abstract fun update(id: IdType, value: InputValueType, it: UpdateStatement)
|
||||
protected abstract fun update(id: IdType, value: InputValueType, it: UpdateBuilder<Int>)
|
||||
protected abstract fun createAndInsertId(value: InputValueType, it: InsertStatement<Number>): IdType
|
||||
|
||||
protected open fun insert(value: InputValueType, it: InsertStatement<Number>) {
|
||||
val id = createAndInsertId(value, it)
|
||||
update(id, value, it as UpdateBuilder<Int>)
|
||||
}
|
||||
@Deprecated(
|
||||
"Replace its \"it\" parameter type with \"UpdateBuilder<Int>\" to actualize method signature. Method with current signature will be removed soon and do not recommended to override anymore"
|
||||
)
|
||||
protected open fun update(id: IdType, value: InputValueType, it: UpdateStatement) = update(
|
||||
id,
|
||||
value,
|
||||
it as UpdateBuilder<Int>
|
||||
)
|
||||
|
||||
protected open suspend fun onBeforeCreate(value: List<InputValueType>) {}
|
||||
|
||||
/**
|
||||
* Use this method to do the something with [values]. You may change and output values in that list and return
|
||||
* changed list of pairs
|
||||
*/
|
||||
protected open suspend fun onAfterCreate(
|
||||
values: List<Pair<InputValueType, ObjectType>>
|
||||
): List<ObjectType> = values.map { it.second }
|
||||
private fun createWithoutNotification(value: InputValueType): ObjectType {
|
||||
return transaction(database) {
|
||||
insert { insert(value, it) }.asObject(value)
|
||||
@ -40,13 +61,18 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
|
||||
onBeforeCreate(values)
|
||||
return transaction(db = database) {
|
||||
values.map { value -> createWithoutNotification(value) }
|
||||
values.map { value -> value to createWithoutNotification(value) }
|
||||
}.let {
|
||||
onAfterCreate(it)
|
||||
}.onEach {
|
||||
_newObjectsFlow.emit(it)
|
||||
}
|
||||
}
|
||||
|
||||
protected open suspend fun onBeforeUpdate(value: List<UpdatedValuePair<IdType, InputValueType>>) {}
|
||||
protected open suspend fun onAfterUpdate(
|
||||
value: List<UpdatedValuePair<InputValueType, ObjectType>>
|
||||
): List<ObjectType> = value.map { it.second }
|
||||
private fun updateWithoutNotification(id: IdType, value: InputValueType): ObjectType? {
|
||||
return transaction(db = database) {
|
||||
update(
|
||||
@ -54,7 +80,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
selectById(this, id)
|
||||
}
|
||||
) {
|
||||
update(id, value, it)
|
||||
update(id, value, it as UpdateBuilder<Int>)
|
||||
}
|
||||
}.let {
|
||||
if (it > 0) {
|
||||
@ -71,7 +97,9 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
|
||||
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
||||
onBeforeUpdate(listOf(id to value))
|
||||
return updateWithoutNotification(id, value).also {
|
||||
return updateWithoutNotification(id, value).let {
|
||||
onAfterUpdate(listOf(value to (it ?: return@let emptyList())))
|
||||
}.firstOrNull().also {
|
||||
if (it != null) {
|
||||
_updatedObjectsFlow.emit(it)
|
||||
}
|
||||
@ -81,9 +109,11 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||
onBeforeUpdate(values)
|
||||
return (
|
||||
transaction(db = database) {
|
||||
values.map { (id, value) -> updateWithoutNotification(id, value) }
|
||||
}.filterNotNull()
|
||||
).onEach {
|
||||
values.mapNotNull { (id, value) -> value to (updateWithoutNotification(id, value) ?: return@mapNotNull null) }
|
||||
}
|
||||
).let {
|
||||
onAfterUpdate(it)
|
||||
}.onEach {
|
||||
_updatedObjectsFlow.emit(it)
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue
|
||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
||||
import org.jetbrains.exposed.sql.statements.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
abstract class AbstractExposedKeyValueRepo<Key, Value>(
|
||||
@ -20,13 +19,27 @@ abstract class AbstractExposedKeyValueRepo<Key, Value>(
|
||||
override val onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow()
|
||||
override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow()
|
||||
|
||||
protected abstract fun update(k: Key, v: Value, it: UpdateStatement)
|
||||
protected abstract fun insert(k: Key, v: Value, it: InsertStatement<Number>)
|
||||
protected abstract fun update(k: Key, v: Value, it: UpdateBuilder<Int>)
|
||||
protected abstract fun insertKey(k: Key, v: Value, it: InsertStatement<Number>)
|
||||
|
||||
protected open fun insert(k: Key, v: Value, it: InsertStatement<Number>) {
|
||||
insertKey(k, v, it)
|
||||
update(k, v, it as UpdateBuilder<Int>)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Replace its \"it\" parameter type with \"UpdateBuilder<Int>\" to actualize method signature. Method with current signature will be removed soon and do not recommended to override anymore"
|
||||
)
|
||||
protected open fun update(k: Key, v: Value, it: UpdateStatement) = update(
|
||||
k,
|
||||
v,
|
||||
it as UpdateBuilder<Int>
|
||||
)
|
||||
|
||||
override suspend fun set(toSet: Map<Key, Value>) {
|
||||
transaction(database) {
|
||||
toSet.mapNotNull { (k, v) ->
|
||||
if (update({ selectById(k) }) { update(k, v, it) } > 0) {
|
||||
if (update({ selectById(k) }) { update(k, v, it as UpdateBuilder<Int>) } > 0) {
|
||||
k to v
|
||||
} else {
|
||||
val inserted = insert {
|
||||
|
@ -5,57 +5,27 @@ import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
||||
import dev.inmo.micro_utils.repos.exposed.*
|
||||
import dev.inmo.micro_utils.repos.exposed.utils.selectPaginated
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
||||
import org.jetbrains.exposed.sql.statements.UpdateBuilder
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
open class ExposedReadKeyValueRepo<Key, Value>(
|
||||
override val database: Database,
|
||||
database: Database,
|
||||
keyColumnAllocator: ColumnAllocator<Key>,
|
||||
valueColumnAllocator: ColumnAllocator<Value>,
|
||||
tableName: String? = null
|
||||
) : ReadKeyValueRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
|
||||
val keyColumn: Column<Key> = keyColumnAllocator()
|
||||
) : ReadKeyValueRepo<Key, Value>, ExposedRepo, AbstractExposedReadKeyValueRepo<Key, Value>(database, tableName) {
|
||||
|
||||
override val keyColumn: Column<Key> = keyColumnAllocator()
|
||||
val valueColumn: Column<Value> = valueColumnAllocator()
|
||||
override val primaryKey: PrimaryKey = PrimaryKey(keyColumn, valueColumn)
|
||||
override val ResultRow.asKey: Key
|
||||
get() = get(keyColumn)
|
||||
override val selectByValue: SqlExpressionBuilder.(Value) -> Op<Boolean> = { valueColumn.eq(it) }
|
||||
override val ResultRow.asObject: Value
|
||||
get() = get(valueColumn)
|
||||
override val selectById: SqlExpressionBuilder.(Key) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
override val primaryKey: Table.PrimaryKey
|
||||
get() = PrimaryKey(keyColumn, valueColumn)
|
||||
|
||||
init { initTable() }
|
||||
|
||||
override suspend fun get(k: Key): Value? = transaction(database) {
|
||||
select { keyColumn.eq(k) }.limit(1).firstOrNull() ?.getOrNull(valueColumn)
|
||||
}
|
||||
|
||||
override suspend fun contains(key: Key): Boolean = transaction(database) {
|
||||
select { keyColumn.eq(key) }.limit(1).any()
|
||||
}
|
||||
|
||||
override suspend fun count(): Long = transaction(database) { selectAll().count() }
|
||||
|
||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = transaction(database) {
|
||||
selectAll().selectPaginated(
|
||||
pagination,
|
||||
keyColumn,
|
||||
reversed
|
||||
) {
|
||||
it[keyColumn]
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean): PaginationResult<Key> = transaction(database) {
|
||||
select { valueColumn.eq(v) }.selectPaginated(
|
||||
pagination,
|
||||
keyColumn,
|
||||
reversed
|
||||
) {
|
||||
it[keyColumn]
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = transaction(database) {
|
||||
selectAll().selectPaginated(
|
||||
pagination,
|
||||
keyColumn,
|
||||
reversed
|
||||
) {
|
||||
it[valueColumn]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,8 @@
|
||||
package dev.inmo.micro_utils.repos.exposed.onetomany
|
||||
|
||||
import dev.inmo.micro_utils.pagination.*
|
||||
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
||||
import dev.inmo.micro_utils.repos.exposed.*
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
typealias ExposedReadOneToManyKeyValueRepo<Key, Value> = ExposedReadKeyValuesRepo<Key, Value>
|
||||
|
||||
@ -13,54 +11,15 @@ open class ExposedReadKeyValuesRepo<Key, Value>(
|
||||
keyColumnAllocator: ColumnAllocator<Key>,
|
||||
valueColumnAllocator: ColumnAllocator<Value>,
|
||||
tableName: String? = null
|
||||
) : ReadKeyValuesRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
|
||||
val keyColumn: Column<Key> = keyColumnAllocator()
|
||||
) : ReadKeyValuesRepo<Key, Value>, ExposedRepo, AbstractExposedReadKeyValuesRepo<Key, Value>(database, tableName) {
|
||||
override val keyColumn: Column<Key> = keyColumnAllocator()
|
||||
override val ResultRow.asKey: Key
|
||||
get() = get(keyColumn)
|
||||
override val selectByValue: SqlExpressionBuilder.(Value) -> Op<Boolean> = { valueColumn.eq(it) }
|
||||
override val ResultRow.asObject: Value
|
||||
get() = get(valueColumn)
|
||||
override val selectById: SqlExpressionBuilder.(Key) -> Op<Boolean> = { keyColumn.eq(it) }
|
||||
val valueColumn: Column<Value> = valueColumnAllocator()
|
||||
|
||||
init { initTable() }
|
||||
|
||||
override suspend fun count(k: Key): Long = transaction(database) { select { keyColumn.eq(k) }.count() }
|
||||
|
||||
override suspend fun count(): Long = transaction(database) { selectAll().count() }
|
||||
|
||||
override suspend fun get(
|
||||
k: Key,
|
||||
pagination: Pagination,
|
||||
reversed: Boolean
|
||||
): PaginationResult<Value> = transaction(database) {
|
||||
select { keyColumn.eq(k) }.paginate(pagination, keyColumn, reversed).map { it[valueColumn] }
|
||||
}.createPaginationResult(
|
||||
pagination,
|
||||
count(k)
|
||||
)
|
||||
|
||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = transaction(database) {
|
||||
selectAll().paginate(pagination, keyColumn, reversed).map { it[keyColumn] }
|
||||
}.createPaginationResult(
|
||||
pagination,
|
||||
count()
|
||||
)
|
||||
|
||||
override suspend fun keys(
|
||||
v: Value,
|
||||
pagination: Pagination,
|
||||
reversed: Boolean
|
||||
): PaginationResult<Key> = transaction(database) {
|
||||
select { valueColumn.eq(v) }.let {
|
||||
it.count() to it.paginate(pagination, keyColumn, reversed).map { it[keyColumn] }
|
||||
}
|
||||
}.let { (count, list) ->
|
||||
list.createPaginationResult(
|
||||
pagination,
|
||||
count
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun contains(k: Key): Boolean = transaction(database) {
|
||||
select { keyColumn.eq(k) }.limit(1).any()
|
||||
}
|
||||
|
||||
override suspend fun contains(k: Key, v: Value): Boolean = transaction(database) {
|
||||
select { keyColumn.eq(k).and(valueColumn.eq(v)) }.limit(1).any()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user