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
|
## 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
|
## 0.12.17
|
||||||
|
|
||||||
* `Versions`:
|
* `Versions`:
|
||||||
|
@ -4,9 +4,9 @@ import dev.inmo.micro_utils.repos.UpdatedValuePair
|
|||||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
import org.jetbrains.exposed.sql.statements.*
|
||||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import java.util.Objects
|
||||||
|
|
||||||
abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
||||||
flowsChannelsSize: Int = 0,
|
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 InsertStatement<Number>.asObject(value: InputValueType): ObjectType
|
||||||
|
|
||||||
protected abstract fun insert(value: InputValueType, it: InsertStatement<Number>)
|
protected abstract fun update(id: IdType, value: InputValueType, it: UpdateBuilder<Int>)
|
||||||
protected abstract fun update(id: IdType, value: InputValueType, it: UpdateStatement)
|
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>) {}
|
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 {
|
private fun createWithoutNotification(value: InputValueType): ObjectType {
|
||||||
return transaction(database) {
|
return transaction(database) {
|
||||||
insert { insert(value, it) }.asObject(value)
|
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> {
|
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
|
||||||
onBeforeCreate(values)
|
onBeforeCreate(values)
|
||||||
return transaction(db = database) {
|
return transaction(db = database) {
|
||||||
values.map { value -> createWithoutNotification(value) }
|
values.map { value -> value to createWithoutNotification(value) }
|
||||||
|
}.let {
|
||||||
|
onAfterCreate(it)
|
||||||
}.onEach {
|
}.onEach {
|
||||||
_newObjectsFlow.emit(it)
|
_newObjectsFlow.emit(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open suspend fun onBeforeUpdate(value: List<UpdatedValuePair<IdType, InputValueType>>) {}
|
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? {
|
private fun updateWithoutNotification(id: IdType, value: InputValueType): ObjectType? {
|
||||||
return transaction(db = database) {
|
return transaction(db = database) {
|
||||||
update(
|
update(
|
||||||
@ -54,7 +80,7 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
|||||||
selectById(this, id)
|
selectById(this, id)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
update(id, value, it)
|
update(id, value, it as UpdateBuilder<Int>)
|
||||||
}
|
}
|
||||||
}.let {
|
}.let {
|
||||||
if (it > 0) {
|
if (it > 0) {
|
||||||
@ -71,7 +97,9 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
|||||||
|
|
||||||
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
||||||
onBeforeUpdate(listOf(id to value))
|
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) {
|
if (it != null) {
|
||||||
_updatedObjectsFlow.emit(it)
|
_updatedObjectsFlow.emit(it)
|
||||||
}
|
}
|
||||||
@ -81,9 +109,11 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
|||||||
onBeforeUpdate(values)
|
onBeforeUpdate(values)
|
||||||
return (
|
return (
|
||||||
transaction(db = database) {
|
transaction(db = database) {
|
||||||
values.map { (id, value) -> updateWithoutNotification(id, value) }
|
values.mapNotNull { (id, value) -> value to (updateWithoutNotification(id, value) ?: return@mapNotNull null) }
|
||||||
}.filterNotNull()
|
}
|
||||||
).onEach {
|
).let {
|
||||||
|
onAfterUpdate(it)
|
||||||
|
}.onEach {
|
||||||
_updatedObjectsFlow.emit(it)
|
_updatedObjectsFlow.emit(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,7 @@ package dev.inmo.micro_utils.repos.exposed.keyvalue
|
|||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.statements.InsertStatement
|
import org.jetbrains.exposed.sql.statements.*
|
||||||
import org.jetbrains.exposed.sql.statements.UpdateStatement
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
abstract class AbstractExposedKeyValueRepo<Key, Value>(
|
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 onNewValue: Flow<Pair<Key, Value>> = _onNewValue.asSharedFlow()
|
||||||
override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow()
|
override val onValueRemoved: Flow<Key> = _onValueRemoved.asSharedFlow()
|
||||||
|
|
||||||
protected abstract fun update(k: Key, v: Value, it: UpdateStatement)
|
protected abstract fun update(k: Key, v: Value, it: UpdateBuilder<Int>)
|
||||||
protected abstract fun insert(k: Key, v: Value, it: InsertStatement<Number>)
|
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>) {
|
override suspend fun set(toSet: Map<Key, Value>) {
|
||||||
transaction(database) {
|
transaction(database) {
|
||||||
toSet.mapNotNull { (k, v) ->
|
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
|
k to v
|
||||||
} else {
|
} else {
|
||||||
val inserted = insert {
|
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.*
|
||||||
import dev.inmo.micro_utils.repos.exposed.utils.selectPaginated
|
import dev.inmo.micro_utils.repos.exposed.utils.selectPaginated
|
||||||
import org.jetbrains.exposed.sql.*
|
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
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
open class ExposedReadKeyValueRepo<Key, Value>(
|
open class ExposedReadKeyValueRepo<Key, Value>(
|
||||||
override val database: Database,
|
database: Database,
|
||||||
keyColumnAllocator: ColumnAllocator<Key>,
|
keyColumnAllocator: ColumnAllocator<Key>,
|
||||||
valueColumnAllocator: ColumnAllocator<Value>,
|
valueColumnAllocator: ColumnAllocator<Value>,
|
||||||
tableName: String? = null
|
tableName: String? = null
|
||||||
) : ReadKeyValueRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
|
) : ReadKeyValueRepo<Key, Value>, ExposedRepo, AbstractExposedReadKeyValueRepo<Key, Value>(database, tableName) {
|
||||||
val keyColumn: Column<Key> = keyColumnAllocator()
|
|
||||||
|
override val keyColumn: Column<Key> = keyColumnAllocator()
|
||||||
val valueColumn: Column<Value> = valueColumnAllocator()
|
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() }
|
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
|
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.ReadKeyValuesRepo
|
||||||
import dev.inmo.micro_utils.repos.exposed.*
|
import dev.inmo.micro_utils.repos.exposed.*
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
|
|
||||||
typealias ExposedReadOneToManyKeyValueRepo<Key, Value> = ExposedReadKeyValuesRepo<Key, Value>
|
typealias ExposedReadOneToManyKeyValueRepo<Key, Value> = ExposedReadKeyValuesRepo<Key, Value>
|
||||||
|
|
||||||
@ -13,54 +11,15 @@ open class ExposedReadKeyValuesRepo<Key, Value>(
|
|||||||
keyColumnAllocator: ColumnAllocator<Key>,
|
keyColumnAllocator: ColumnAllocator<Key>,
|
||||||
valueColumnAllocator: ColumnAllocator<Value>,
|
valueColumnAllocator: ColumnAllocator<Value>,
|
||||||
tableName: String? = null
|
tableName: String? = null
|
||||||
) : ReadKeyValuesRepo<Key, Value>, ExposedRepo, Table(tableName ?: "") {
|
) : ReadKeyValuesRepo<Key, Value>, ExposedRepo, AbstractExposedReadKeyValuesRepo<Key, Value>(database, tableName) {
|
||||||
val keyColumn: Column<Key> = keyColumnAllocator()
|
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()
|
val valueColumn: Column<Value> = valueColumnAllocator()
|
||||||
|
|
||||||
init { initTable() }
|
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