Draft of SERDHA storage driver

This commit is contained in:
Andrew Golovashevich 2025-02-22 11:06:42 +03:00
parent 1f6abcb8e1
commit 3532914d27
25 changed files with 1168 additions and 17 deletions

View File

@ -1,2 +1,3 @@
kotlin.native.ignoreDisabledTargets=true
kotlin.suppressGradlePluginWarnings=IncorrectCompileOnlyDependencyWarning
serdhaVersion=0.0

View File

@ -0,0 +1,38 @@
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.defineAllMultiplatformTargets
buildscript {
repositories {
mavenCentral()
maven("https://maven.landgrafhomyak.ru/")
}
dependencies {
classpath("ru.landgrafhomyak.kotlin:kotlin-mpp-gradle-build-helper:v0.2k2.0.20")
}
}
plugins {
kotlin("multiplatform") version "2.0.20"
}
val serdhaVersion: String by project
repositories {
mavenCentral()
maven("https://maven.landgrafhomyak.ru/")
}
kotlin {
jvmToolchain(21)
defineAllMultiplatformTargets()
sourceSets {
commonMain {
dependencies {
implementation("ru.landgrafhomyak.db.serdha:serdha-0-api:$serdhaVersion")
implementation(project(":storage-serdha:schema"))
compileOnly(project(":storage-api"))
}
}
}
}

View File

@ -7,7 +7,7 @@ import kotlin.jvm.JvmName
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
internal inline fun <qUE : Any, tUE : Any> SelectQuery.Folding.Constructor.Scope<qUE, tUE>.COUNT() =
this.foldRows(this.createReducer(COUNT)) { linker -> linker.link(linker.rUE.C_Counter) }
this.foldRows(this.createReducer(COUNT)) { linker -> linker.link(linker.uExt.C_Counter) }
internal inline fun <qUE : Any, tUE : Any> SelectQuery.Folding.Constructor.Scope<qUE, tUE>.HAS_ROWS() =
this.foldRows(this.createReducer(HAS_ROWS)) { linker -> linker.link(linker.rUE.C_Flag) }
this.foldRows(this.createReducer(HAS_ROWS)) { linker -> linker.link(linker.uExt.C_Flag) }

View File

@ -10,6 +10,7 @@ import kotlin.contracts.contract
import kotlin.jvm.JvmName
import ru.landgrafhomyak.db.serdha0.api.LowLevelApi
import ru.landgrafhomyak.db.serdha0.api.queries._Query
import ru.landgrafhomyak.db.serdha0.api.runtime.Executor
import ru.landgrafhomyak.db.serdha0.api.runtime.InputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
@ -37,6 +38,14 @@ internal inline fun <R> _safeAutoClose(onAbort: () -> Unit = {}, onSuccess: () -
return ret
}
suspend inline fun <R> Executor.transaction(@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") scope: suspend (Transaction) -> R): R {
val t = this._startTransaction()
_safeAutoClose(onAbort = { t.rollback() }, onSuccess = { t.commit() }) {
return scope(t)
}
}
class ExpectedOneRowException() : Exception()
class TooManyRowsException() : Exception()
@ -45,6 +54,11 @@ suspend inline fun <_qUE : Any, R> Transaction.selectOneOrError(
params: (qUE: _qUE, i: InputRow<_qUE>) -> Unit,
result: (qUE: _qUE, o: OutputRow<_qUE>) -> R
): R {
contract {
callsInPlace(params, InvocationKind.EXACTLY_ONCE)
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
val i = this._executeQuery(compiledQuery)
_safeAutoClose(onAbort = { i._abort() }) {
params(compiledQuery.uExt, i)
@ -59,5 +73,84 @@ suspend inline fun <_qUE : Any, R> Transaction.selectOneOrError(
throw TooManyRowsException()
}
return ret
}
suspend inline fun <_qUE : Any, R> Transaction.selectOneOrNull(
compiledQuery: _Query.Params2Table<_qUE>,
params: (qUE: _qUE, i: InputRow<_qUE>) -> Unit,
result: (qUE: _qUE, o: OutputRow<_qUE>) -> R
): R? {
contract {
callsInPlace(params, InvocationKind.EXACTLY_ONCE)
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
val i = this._executeQuery(compiledQuery)
_safeAutoClose(onAbort = { i._abort() }) {
params(compiledQuery.uExt, i)
}
val o = i._finish()
val ret: R
_safeAutoClose(onAbort = { o._abort() }, onSuccess = { o._finish() }) {
if (!o._next())
return null
ret = result(compiledQuery.uExt, o)
if (o._next())
throw TooManyRowsException()
}
return ret
}
suspend inline fun <_qUE : Any, E> Transaction.insertMany(
compiledQuery: _Query.Table2Void<_qUE>,
collection: Iterable<E>,
transform: (qUE: _qUE, i: InputRow<_qUE>, e: E) -> Unit
) {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
val i = this._executeQuery(compiledQuery)
_safeAutoClose(onAbort = { i._abort() }) {
for (e in collection) {
i._next()
transform(compiledQuery.uExt, i, e)
}
}
i._finish()
}
suspend inline fun <_qUE : Any> Transaction.executeNoReturn(
compiledQuery: _Query.Params2Table<_qUE>,
params: (qUE: _qUE, i: InputRow<_qUE>) -> Unit,
) {
contract {
callsInPlace(params, InvocationKind.EXACTLY_ONCE)
}
val i = this._executeQuery(compiledQuery)
_safeAutoClose(onAbort = { i._abort() }) {
params(compiledQuery.uExt, i)
}
val o = i._finish()
_safeAutoClose(onAbort = { o._abort() }, onSuccess = { o._finish() }) {
if (o._next())
throw TooManyRowsException()
}
}
suspend inline fun <_qUE : Any> Transaction.executeNoReturn(
compiledQuery: _Query.Params2Void<_qUE>,
params: (qUE: _qUE, i: InputRow<_qUE>) -> Unit,
) {
contract {
callsInPlace(params, InvocationKind.EXACTLY_ONCE)
}
val i = this._executeQuery(compiledQuery)
_safeAutoClose(onAbort = { i._abort() }) {
params(compiledQuery.uExt, i)
}
i._finish()
}

View File

@ -5,10 +5,9 @@ import ru.landgrafhomyak.db.serdha0.api.table.TableConstructor
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
class T_Chats private constructor(context: TableConstructor.Scope<T_Chats>) {
val C_RowId = context.rowId_column
val C_RowId = context.rowIdColumn
val C_TgCid = context.column("telegram::chat_id", context.types.S64)
val U_RowId = context.rowId_uniqueConstraint
val U_TgCid = context.uniqueIndex("telegram::chat_id", true, this.C_TgCid)
companion object Constructor : TableConstructor<T_Chats> {

View File

@ -8,15 +8,16 @@ import ru.landgrafhomyak.db.serdha0.api.table.TableConstructor
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
class T_QueueSets private constructor(creator: TableConstructor.Scope<T_QueueSets>, chatsTable: Table<T_Chats, *>) {
val C_RowId = creator.rowId_column
val C_RowId = creator.rowIdColumn
val C_Chat = creator.foreignRowReference("chat", chatsTable, ForeignRowReference.OnDelete.CASCADE)
val C_TgMid = creator.column("telegram::message_id", creator.types.U64)
val C_IsOpen = creator.column("is_open", creator.types.BOOLEAN)
val C_Name = creator.column("name", creator.types.STRING)
val C_IsOpen = creator.column("is_open", creator.types.BOOLEAN)
val U_RowId = creator.rowId_uniqueConstraint
val U_TgMid = creator.uniqueIndex("telegram::message_id", true, this.C_Chat, this.C_TgMid)
val D_IsOpen = creator.defaultValue(this.C_IsOpen, true)
private class _Constructor(private val chatsTable: Table<T_Chats, *>) : TableConstructor<T_QueueSets> {
override fun createTable(context: TableConstructor.Scope<T_QueueSets>) =
T_QueueSets(context, this.chatsTable)

View File

@ -8,12 +8,11 @@ import ru.landgrafhomyak.db.serdha0.api.table.TableConstructor
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
class T_Queues private constructor(creator: TableConstructor.Scope<T_Queues>, queueSetsTable: Table<T_QueueSets, *>) {
val C_RowId = creator.rowId_column
val C_RowId = creator.rowIdColumn
val C_QueueSet = creator.foreignRowReference("chat", queueSetsTable, ForeignRowReference.OnDelete.CASCADE)
val C_Name = creator.column("name", creator.types.STRING)
val C_Ordinal = creator.column("ordinal", creator.types.U8)
val U_RowId = creator.rowId_uniqueConstraint
val U_Id = creator.uniqueIndex("id", true, this.C_QueueSet, this.C_Ordinal)
private class _Constructor(private val queueSetsTable: Table<T_QueueSets, *>) : TableConstructor<T_Queues> {

View File

@ -18,13 +18,14 @@ class T_User2Queue private constructor(
context: TableConstructor.Scope<T_User2Queue>,
usersTable: Table<T_Users, *>, queueSetsTable: Table<T_QueueSets, *>, queuesTable: Table<T_Queues, *>
) {
val C_RowId = context.rowIdColumn
val C_User = context.foreignRowReference("user", usersTable, ForeignRowReference.OnDelete.CASCADE)
val C_QueueSet = context.foreignRowReference("queue_set", queueSetsTable, ForeignRowReference.OnDelete.CASCADE)
val C_Queue = context.foreignRowReference("queue", context.types.nullableOf(context.types.ROW_ID(queuesTable)), queuesTable, ForeignRowReference.OnDelete.CASCADE)
val C_Ordinal = context.column("ordinal", context.types.U8)
val U_UserInQueue = context.uniqueIndex("user_in_queue", true, this.C_User, this.C_QueueSet)
val U_QueueInSet = context.uniqueIndex("queue_in_set", true, this.C_QueueSet, this.C_Queue, this.C_Ordinal)
val U_UserInQueueSet = context.uniqueIndex("user_in_queue_set", true, this.C_User, this.C_QueueSet)
val U_UserInQueue = context.uniqueIndex("user_in_queue", true, this.C_QueueSet, this.C_Queue, this.C_Ordinal)
val H_QueueRef = context.checkConstraint("queue_ref", CheckQueueRefs(queueSetsTable))
@ -71,7 +72,7 @@ class T_User2Queue private constructor(
val hasRows: Boolean = transaction.selectOneOrError(
this.selectQueuesCount,
params = { qUE, i -> i[qUE.P_QueueSetId] = row[rowUE.C_QueueSet] },
result = { qUE, o -> o[qUE.C_HasQueries] }
result = { qUE, o -> return@selectOneOrError o[qUE.C_HasQueries] }
)
return hasRows == (row[rowUE.C_Queue] == null)

View File

@ -6,11 +6,10 @@ import ru.landgrafhomyak.db.serdha0.api.table.TableConstructor
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
class T_Users private constructor(context: TableConstructor.Scope<T_Users>) {
val C_RowId = context.rowId_column
val C_RowId = context.rowIdColumn
val C_TgUid = context.column("telegram::user_id", context.types.U64)
val C_DisplayName = context.column("display_name", context.types.STRING)
val U_RowId = context.rowId_uniqueConstraint
val U_TgUid = context.uniqueIndex("telegram::user_id", true, this.C_TgUid)
companion object Constructor : TableConstructor<T_Users> {

@ -1 +1 @@
Subproject commit 8961cea200b07b87a84c294a044289a62244043f
Subproject commit 36ced5d74dee0694d0040a7cfffe917c477db695

View File

@ -0,0 +1,31 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha
import kotlin.jvm.JvmStatic
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.STRING
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.db.serdha0.api.misc.Column
import ru.landgrafhomyak.db.serdha0.api.misc.DatabaseType
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
import ru.landgrafhomyak.db.serdha0.api.table.RowId
internal class FoundQueue(
val rowId: RowId<T_QueueSets>,
val name: String,
val isOpen: Boolean
) {
@Suppress("PropertyName")
interface QueueSetRow<qUE : Any> {
val C_QsRowId: Column<RowId<T_QueueSets>, DatabaseType.ROW_ID<T_QueueSets>, qUE>
val C_QsName: Column<String, STRING, qUE>
val C_QsIsOpen: Column<Boolean, DatabaseType.BOOLEAN, qUE>
}
companion object {
@JvmStatic
fun <qUE : QueueSetRow<qUE>> fromRow(ue: qUE, row: OutputRow<qUE>) = FoundQueue(
rowId = row[ue.C_QsRowId],
name = row[ue.C_QsName],
isOpen = row[ue.C_QsIsOpen]
)
}
}

View File

@ -0,0 +1,40 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha
import kotlin.jvm.JvmStatic
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.STRING
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U8
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Users
import ru.landgrafhomyak.db.serdha0.api.misc.Column
import ru.landgrafhomyak.db.serdha0.api.misc.DatabaseType
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
import ru.landgrafhomyak.db.serdha0.api.table.RowId
internal class FoundUserInQueue(
val linkRowId: RowId<T_User2Queue>,
val userRowId: RowId<T_Users>,
val userDisplayName: String,
val queueRef: RowId<T_Queues>?,
val ordinal: UByte?
) {
@Suppress("PropertyName")
interface UserInQueueRow<qUE : Any> {
val C_RowId: Column<RowId<T_User2Queue>, DatabaseType.ROW_ID<T_User2Queue>, qUE>
val C_URowId: Column<RowId<T_Users>, DatabaseType.ROW_ID<T_Users>, qUE>
val C_UDisplayName: Column<String, STRING, qUE>
val C_QRowId: Column<RowId<T_Queues>?, DatabaseType.Nullable<RowId<T_Queues>, DatabaseType.ROW_ID<T_Queues>>, qUE>
val C_Ordinal: Column<UByte?, DatabaseType.Nullable<UByte, U8>, qUE>
}
companion object {
@JvmStatic
fun <qUE : UserInQueueRow<qUE>> fromRow(ue: qUE, row: OutputRow<qUE>) = FoundUserInQueue(
linkRowId = row[ue.C_RowId],
userRowId = row[ue.C_URowId],
userDisplayName = row[ue.C_UDisplayName],
queueRef = row[ue.C_QRowId],
ordinal = row[ue.C_Ordinal]
)
}
}

View File

@ -0,0 +1,256 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha
import ru.landgrafhomyak.bgtu.db0.storage.api.ModeratorPermissions
import ru.landgrafhomyak.bgtu.db0.storage.api.Storage
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.D_RemoveUserFromQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.I_AddQueueSet
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.I_AddQueues
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.I_AddUserToQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.S_FindFreeOrdinalInQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.S_FindNeighbourQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.S_FindQueueSet
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.S_FindUserInQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.S_FirstQueueInSet
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.U_ChangeQueueState
import ru.landgrafhomyak.bgtu.db0.storage.serdha.queries.U_MoveUserInQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.executeNoReturn
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.insertMany
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.selectOneOrError
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.selectOneOrNull
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.transaction
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
import ru.landgrafhomyak.db.serdha0.api.runtime.Executor
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
import ru.landgrafhomyak.db.serdha0.api.table.RowId
import ru.landgrafhomyak.bgtu.db0.storage.api.Storage as IStorage
@Suppress("PrivatePropertyName")
class SerdhaStorage(module: Module<M_V0>, private val executor: Executor) : IStorage {
private val _q_addQueueSet = module.createQuery(I_AddQueueSet(module))
private val _q_addQueues = module.createQuery(I_AddQueues(module))
/*override*/ suspend fun allocQueue(chat: Long, message: Long, setName: String, queueNames: List<String>) = this.executor.transaction { t ->
val qsRowId = t.selectOneOrError(
compiledQuery = this._q_addQueueSet,
params = { qUE, p ->
p[qUE.P_TgCid] = chat
p[qUE.P_TgMid] = message.toULong()
p[qUE.P_Name] = setName
},
result = { qUE, r ->
return@selectOneOrError r[qUE.C_RowId]
}
)
var i: UByte = 0u
t.insertMany(this._q_addQueues, queueNames) { qUE, p, e ->
p[qUE.P_QueueSet] = qsRowId
p[qUE.P_Ordinal] = i++
p[qUE.P_Name] = e
}
}
private val _q_changeQueueState = module.createQuery(U_ChangeQueueState(module))
@Suppress("FunctionName")
private suspend fun _closeOrOpenQueue(chat: Long, message: Long, newIsOpen: Boolean): Storage.Result_QueueCloseOrOpen = this.executor.transaction { t ->
val qs = t.selectOneOrNull(
compiledQuery = this._q_changeQueueState,
params = { qUE, p ->
p[qUE.P_TgCid] = chat
p[qUE.P_TgMid] = message.toULong()
p[qUE.P_NewState] = newIsOpen
},
// result = FoundQueue::fromRow
result = { qUE, r ->
if (r[qUE.C_OldIsOpen] == newIsOpen)
return@transaction Storage.Result_QueueCloseOrOpen.ALREADY_IN_STATE
return@selectOneOrNull FoundQueue.fromRow(qUE, r)
}
)
if (qs == null)
return@transaction Storage.Result_QueueCloseOrOpen.QUEUE_NOT_FOUND
return@transaction Storage.Result_QueueCloseOrOpen.SUCCESSFUL(this._formatQueueSet(qs))
}
/*override*/ suspend fun closeQueue(chat: Long, message: Long): Storage.Result_QueueCloseOrOpen =
this._closeOrOpenQueue(chat, message, false)
/*override*/ suspend fun reopenQueue(chat: Long, message: Long): Storage.Result_QueueCloseOrOpen =
this._closeOrOpenQueue(chat, message, true)
private val _q_findQueueSet = module.createQuery(S_FindQueueSet(module))
@Suppress("FunctionName")
private suspend fun _findQueueSet(transaction: Transaction, chat: Long, message: Long): FoundQueue? =
transaction.selectOneOrNull(
compiledQuery = this._q_findQueueSet.byMessage,
params = { ue, r ->
r[ue.P_TgCid] = chat
r[ue.P_TgMid] = message.toULong()
},
result = FoundQueue::fromRow
)
private val _q_findUserInQueue = module.createQuery(S_FindUserInQueue(module))
@Suppress("FunctionName")
private suspend fun _findUserInQueue(transaction: Transaction, qs: FoundQueue, user: Long, displayName: String): FoundUserInQueue =
transaction.selectOneOrError(
compiledQuery = this._q_findUserInQueue,
params = { ue, r ->
r[ue.P_QueueSet] = qs.rowId
r[ue.P_TgUid] = user.toULong()
r[ue.P_UDisplayName] = displayName
},
result = FoundUserInQueue::fromRow
)
private val _q_findFirstQueue = module.createQuery(S_FirstQueueInSet(module))
private val _q_findOrdinal = module.createQuery(S_FindFreeOrdinalInQueue(module))
private val _q_addUser2Queue = module.createQuery(I_AddUserToQueue(module))
/*override*/ suspend fun addUserToQueue(chat: Long, message: Long, user: Long, userDisplayName: String): Storage.Result_AddOrRemoveUser = this.executor.transaction { transaction ->
val qs = this._findQueueSet(transaction, chat, message) ?: return@transaction Storage.Result_AddOrRemoveUser.QUEUE_NOT_FOUND
if (!qs.isOpen) return@transaction Storage.Result_AddOrRemoveUser.QUEUE_IS_FINAL
val u = this._findUserInQueue(transaction, qs, user, userDisplayName)
if (u.ordinal != null) return@transaction Storage.Result_AddOrRemoveUser.ALREADY_IN_STATE
val q = transaction.selectOneOrNull(
compiledQuery = this._q_findFirstQueue,
params = { ue, r -> r[ue.P_QueueSet] = qs.rowId },
result = { ue, r -> return@selectOneOrNull r[ue.C_Queue] }
)
val o = this._q_findOrdinal.findFirstOrdinal(transaction, 0u, qs.rowId, q) ?: return@transaction Storage.Result_AddOrRemoveUser.QUEUE_OVERFLOW
transaction.executeNoReturn(this._q_addUser2Queue) { x, r ->
r[x.P_QueueSet] = qs.rowId
r[x.P_Queue] = q
r[x.P_User] = u.userRowId
r[x.P_Ordinal] = o
}
return@transaction Storage.Result_AddOrRemoveUser.SUCCESSFUL(this._formatQueueSet(qs))
}
private val _q_removeUserFromQueue = module.createQuery(D_RemoveUserFromQueue(module))
/*override*/ suspend fun removeUserFromQueue(chat: Long, message: Long, user: Long, userDisplayName: String): Storage.Result_AddOrRemoveUser = this.executor.transaction { transaction ->
val qs = this._findQueueSet(transaction, chat, message) ?: return@transaction Storage.Result_AddOrRemoveUser.QUEUE_NOT_FOUND
if (!qs.isOpen) return@transaction Storage.Result_AddOrRemoveUser.QUEUE_IS_FINAL
val u = this._findUserInQueue(transaction, qs, user, userDisplayName)
if (u.ordinal == null) return@transaction Storage.Result_AddOrRemoveUser.ALREADY_IN_STATE
transaction.executeNoReturn(this._q_removeUserFromQueue) { x, r ->
r[x.P_RowId] = u.linkRowId
}
return@transaction Storage.Result_AddOrRemoveUser.SUCCESSFUL(this._formatQueueSet(qs))
}
private val _q_findNeighbourQueue = module.createQuery(S_FindNeighbourQueue(module))
private val _q_moveUserInQueue = module.createQuery(U_MoveUserInQueue(module))
@Suppress("FunctionName")
private suspend fun _moveUserToNeighbourQueue(chat: Long, message: Long, user: Long, userDisplayName: String, query: SelectQuery.Simple<S_FindNeighbourQueue.Query>): Storage.Result_MoveToNextOrPrevQueue = this.executor.transaction { transaction ->
val qs = this._findQueueSet(transaction, chat, message) ?: return@transaction Storage.Result_MoveToNextOrPrevQueue.QUEUE_NOT_FOUND
if (!qs.isOpen) return@transaction Storage.Result_MoveToNextOrPrevQueue.QUEUE_IS_FINAL
val u = this._findUserInQueue(transaction, qs, user, userDisplayName)
if (u.ordinal == null)
return@transaction Storage.Result_MoveToNextOrPrevQueue.NOT_IN_QUEUE
if (u.queueRef == null)
return@transaction Storage.Result_MoveToNextOrPrevQueue.ON_EDGE
val qo = transaction.selectOneOrError(
this._q_findNeighbourQueue.getOrdinal,
params = { x, r -> r[x.P_RowId] = u.queueRef },
result = { x, r -> return@selectOneOrError r[x.C_Ordinal] }
)
val q = transaction.selectOneOrNull(
compiledQuery = query,
params = { ue, r -> r[ue.P_QueueSet] = qs.rowId; r[ue.P_OldOrdinal] = qo },
result = { ue, r -> return@selectOneOrNull r[ue.C_NewQueue] }
)
if (q == null)
return@transaction Storage.Result_MoveToNextOrPrevQueue.ON_EDGE
val o = this._q_findOrdinal.findFirstOrdinal(transaction, 0u, qs.rowId, q) ?: return@transaction Storage.Result_MoveToNextOrPrevQueue.QUEUE_OVERFLOW
transaction.executeNoReturn(this._q_moveUserInQueue) { x, r ->
r[x.P_RowId] = u.linkRowId
r[x.P_NewQueue] = q
r[x.P_NewOrdinal] = o
}
return@transaction Storage.Result_MoveToNextOrPrevQueue.SUCCESSFUL(this._formatQueueSet(qs))
}
/*override*/ suspend fun moveUserToNextQueue(chat: Long, message: Long, user: Long, userDisplayName: String): Storage.Result_MoveToNextOrPrevQueue =
this._moveUserToNeighbourQueue(chat, message, user, userDisplayName, this._q_findNeighbourQueue.next)
/*override*/ suspend fun moveUserToPrevQueue(chat: Long, message: Long, user: Long, userDisplayName: String): Storage.Result_MoveToNextOrPrevQueue =
this._moveUserToNeighbourQueue(chat, message, user, userDisplayName, this._q_findNeighbourQueue.prev)
@Suppress("FunctionName")
private suspend fun _moveUserInQueue(
chat: Long, message: Long, user: Long, userDisplayName: String,
query: suspend (t: Transaction, o: UByte, qs: RowId<T_QueueSets>, q: RowId<T_Queues>?) -> UByte?
): Storage.Result_MoveToStartOrEnd = this.executor.transaction { transaction ->
val qs = this._findQueueSet(transaction, chat, message) ?: return@transaction Storage.Result_MoveToStartOrEnd.QUEUE_NOT_FOUND
if (!qs.isOpen) return@transaction Storage.Result_MoveToStartOrEnd.QUEUE_IS_FINAL
val u = this._findUserInQueue(transaction, qs, user, userDisplayName)
val o = query(transaction, u.ordinal ?: return@transaction Storage.Result_MoveToStartOrEnd.NOT_IN_QUEUE, qs.rowId, u.queueRef) ?: return@transaction Storage.Result_MoveToStartOrEnd.ON_EDGE
transaction.executeNoReturn(this._q_moveUserInQueue) { x, r ->
r[x.P_RowId] = u.linkRowId
r[x.P_NewQueue] = u.queueRef
r[x.P_NewOrdinal] = o
}
return@transaction Storage.Result_MoveToStartOrEnd.SUCCESSFUL(this._formatQueueSet(qs))
}
/*override*/ suspend fun moveUserToStartOfQueue(chat: Long, message: Long, user: Long, displayName: String) =
this._moveUserInQueue(chat, message, user, displayName, this._q_findOrdinal::findOrdinalBefore)
/*override*/ suspend fun moveUserToEndOfQueue(chat: Long, message: Long, user: Long, displayName: String) =
this._moveUserInQueue(chat, message, user, displayName, this._q_findOrdinal::findOrdinalAfter)
override fun addModerator(chat: Long, user: Long): Boolean {
TODO("Not yet implemented")
}
override fun removeModerator(chat: Long, message: Long): Boolean {
TODO("Not yet implemented")
}
override fun getPermissions(chat: Long, user: Long): ModeratorPermissions? {
TODO("Not yet implemented")
}
override fun setPermission(chat: Long, user: Long, permissionType: ModeratorPermissions.PermissionType, value: Boolean): Storage.Result_SetModeratorPermission {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,23 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.DeleteQuery
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class D_RemoveUserFromQueue private constructor(context: DeleteQuery.SingleRow.Constructor.Scope<D_RemoveUserFromQueue, T_User2Queue>) {
val P_RowId = context.rowToRemove
private class _Constructor(
override val targetTable: Table<T_User2Queue, *>
) : DeleteQuery.SingleRow.Constructor<D_RemoveUserFromQueue, T_User2Queue> {
override fun createDeleteSingleRowWithReturning(context: DeleteQuery.SingleRow.Constructor.Scope<D_RemoveUserFromQueue, T_User2Queue>) =
D_RemoveUserFromQueue(context)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>) : DeleteQuery.SingleRow.Constructor<D_RemoveUserFromQueue, T_User2Queue> = _Constructor(module.uExt.user2queue)
}
}

View File

@ -0,0 +1,62 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.S64
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.STRING
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U64
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Chats
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.InsertQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class I_AddQueueSet(private val module: Module<M_V0>) : _Query.Constructor<InsertQuery.FromSubquery<I_AddQueueSet.I_AddQueueSet>> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope): InsertQuery.FromSubquery<I_AddQueueSet> {
return outQueries.insertFromSubquery(
I_AddQueueSet.Constructor(
this.module.uExt.queueSets,
internalQueries.insertSingleRow(I_EnsureChat.Constructor(this.module.uExt.chats))
)
)
}
class I_EnsureChat private constructor(context: InsertQuery.SingleRow.Constructor.Scope<I_EnsureChat, T_Chats>) {
val P_TgCid = context.queryParam("tg_cid", context.types.S64)
init {
context.insertParam(context.tt.uExt.C_TgCid, this.P_TgCid)
context.onConflictUpdate(context.tt.uExt.U_TgCid) {}
}
val C_RowId = context.returnInsertedValue("row_id", context.tt.uExt.C_RowId)
class Constructor(override val targetTable: Table<T_Chats, *>) : InsertQuery.SingleRow.Constructor<I_EnsureChat, T_Chats> {
override fun createInsertSingleRowWithReturning(context: InsertQuery.SingleRow.Constructor.Scope<I_EnsureChat, T_Chats>) =
I_EnsureChat(context)
}
}
class I_AddQueueSet private constructor(context: InsertQuery.FromSubquery.Constructor.Scope<I_AddQueueSet, T_QueueSets, I_EnsureChat>) {
val P_TgCid = context.queryParam("chat_id", context.types.S64)
val P_TgMid = context.queryParam("message_id", context.types.U64)
val P_Name = context.queryParam("name", context.types.STRING)
init {
context.sourceQueryParams.redirect(context.src.uExt.P_TgCid, this.P_TgCid)
context.insertFromSubquery(context.tt.uExt.C_Chat, context.src.uExt.C_RowId)
context.insertParam(context.tt.uExt.C_TgMid, this.P_TgMid)
context.insertParam(context.tt.uExt.C_Name, this.P_Name)
}
val C_RowId = context.returnInsertedValue("row_id", context.tt.uExt.C_RowId)
class Constructor(override val targetTable: Table<T_QueueSets, *>, override val selector: _Selectable<I_EnsureChat>) : InsertQuery.FromSubquery.Constructor<I_AddQueueSet, T_QueueSets, I_EnsureChat> {
override fun createInsertSingleRowWithReturning(context: InsertQuery.FromSubquery.Constructor.Scope<I_AddQueueSet, T_QueueSets, I_EnsureChat>) =
I_AddQueueSet(context)
}
}
}

View File

@ -0,0 +1,35 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.STRING
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U8
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.InsertQuery
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class I_AddQueues private constructor(context: InsertQuery.MultipleRows.Constructor.Scope<I_AddQueues, T_Queues>, qsTable: Table<T_QueueSets, *>) {
val P_QueueSet = context.inputColumn("queue_set", context.types.ROW_ID(qsTable))
val P_Name = context.inputColumn("name", context.types.STRING)
val P_Ordinal = context.inputColumn("ordinal", context.types.U8)
init {
context.insertColumn(context.tt.uExt.C_QueueSet, this.P_QueueSet)
context.insertColumn(context.tt.uExt.C_Name, this.P_Name)
context.insertColumn(context.tt.uExt.C_Ordinal, this.P_Ordinal)
}
private class _Constructor(private val module: Module<M_V0>) : InsertQuery.MultipleRows.Constructor<I_AddQueues, T_Queues> {
override val targetTable: Table<T_Queues, *>
get() = this.module.uExt.queues
override fun createInsertMultipleRows(context: InsertQuery.MultipleRows.Constructor.Scope<I_AddQueues, T_Queues>) =
I_AddQueues(context, this.module.uExt.queueSets)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>) : InsertQuery.MultipleRows.Constructor<I_AddQueues, T_Queues> = _Constructor(module)
}
}

View File

@ -0,0 +1,32 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.InsertQuery
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class I_AddUserToQueue private constructor(context: InsertQuery.SingleRow.Constructor.Scope<I_AddUserToQueue, T_User2Queue>) {
val P_QueueSet = context.queryParam("queue_set", context.tt.uExt.C_QueueSet.type)
val P_Queue = context.queryParam("queue", context.tt.uExt.C_Queue.type)
val P_User = context.queryParam("user", context.tt.uExt.C_User.type)
val P_Ordinal = context.queryParam("ordinal", context.tt.uExt.C_Ordinal.type)
init {
context.insertParam(context.tt.uExt.C_QueueSet, this.P_QueueSet)
context.insertParam(context.tt.uExt.C_Queue, this.P_Queue)
context.insertParam(context.tt.uExt.C_User, this.P_User)
context.insertParam(context.tt.uExt.C_Ordinal, this.P_Ordinal)
}
private class _Constructor(
override val targetTable: Table<T_User2Queue, *>
) : InsertQuery.SingleRow.Constructor<I_AddUserToQueue, T_User2Queue> {
override fun createInsertSingleRowWithReturning(context: InsertQuery.SingleRow.Constructor.Scope<I_AddUserToQueue, T_User2Queue>) = I_AddUserToQueue(context)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>) : InsertQuery.SingleRow.Constructor<I_AddUserToQueue, T_User2Queue> = _Constructor(module.uExt.user2queue)
}
}

View File

@ -0,0 +1,178 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U8
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.selectOneOrNull
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.db.serdha0.api.misc.Column
import ru.landgrafhomyak.db.serdha0.api.misc.DatabaseType
import ru.landgrafhomyak.db.serdha0.api.misc.FiltersScope
import ru.landgrafhomyak.db.serdha0.api.misc.IntermediateColumn
import ru.landgrafhomyak.db.serdha0.api.misc.QueryParam
import ru.landgrafhomyak.db.serdha0.api.misc.Reducer
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
import ru.landgrafhomyak.db.serdha0.api.runtime.InputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
import ru.landgrafhomyak.db.serdha0.api.table.RowId
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate", "PrivatePropertyName")
class S_FindFreeOrdinalInQueue(private val module: Module<M_V0>) : _Query.Constructor<S_FindFreeOrdinalInQueue.EntryPoints> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope) =
EntryPoints(this.module, outQueries)
@Suppress("PrivatePropertyName", "FoldInitializerAndIfToElvis")
class EntryPoints(module: Module<M_V0>, outQueries: _Query.Constructor.Scope) {
private val toFront_Q = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Dec) { t -> t.C_Queue })
private val toFront_QS = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Dec) { t -> t.C_QueueSet })
private val toBack_Q = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Inc) { t -> t.C_Queue })
private val toBack_QS = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Inc) { t -> t.C_QueueSet })
private val first_Q = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Inc.Inclusive) { t -> t.C_Queue })
private val first_QS = outQueries.selectReducing(Query.Constructor(module.uExt.user2queue, Inc.Inclusive) { t -> t.C_QueueSet })
@Suppress("DuplicatedCode", "FunctionName")
private suspend fun _execute(
t: Transaction,
qq: SelectQuery.Reducing<Query<RowId<T_Queues>?, DatabaseType.Nullable<RowId<T_Queues>, DatabaseType.ROW_ID<T_Queues>>>>,
qqs: SelectQuery.Reducing<Query<RowId<T_QueueSets>, DatabaseType.ROW_ID<T_QueueSets>>>,
o: UByte,
qs: RowId<T_QueueSets>,
q: RowId<T_Queues>?
): UByte? {
if (q == null) {
return t.selectOneOrNull(
qqs,
params = { x, r -> r[x.P_Ordinal] = o;r[x._P_Selector] = qs },
result = { x, r -> return@selectOneOrNull r[x.C_Ordinal] }
)
} else {
return t.selectOneOrNull(
qq,
params = { x, r -> r[x.P_Ordinal] = o;r[x._P_Selector] = q },
result = { x, r -> return@selectOneOrNull r[x.C_Ordinal] }
)
}
}
suspend fun findOrdinalBefore(t: Transaction, o: UByte, qs: RowId<T_QueueSets>, q: RowId<T_Queues>?): UByte? {
val f = this._execute(t, this.toFront_Q, this.toFront_QS, o, qs, q)
if (f == null) return if (o.toUInt() == 0u) null else (o - 1u).toUByte()
if (f.toUInt() == 0u) return null
return (f - 1u).toUByte()
}
suspend fun findOrdinalAfter(t: Transaction, o: UByte, qs: RowId<T_QueueSets>, q: RowId<T_Queues>?): UByte? {
val f = this._execute(t, this.toBack_Q, this.toBack_QS, o, qs, q)
if (f == null) return if (o.toUInt() == 255u) null else (o + 1u).toUByte()
if (f.toUInt() == 255u) return null
return (f + 1u).toUByte()
}
suspend fun findFirstOrdinal(t: Transaction, o: UByte, qs: RowId<T_QueueSets>, q: RowId<T_Queues>?): UByte? {
val f = this._execute(t, this.first_Q, this.first_QS, o, qs, q)
if (f == null) return 0u
if (f.toUInt() == 255u) return null
return (f + 1u).toUByte()
}
}
private abstract class _OrdinalSelectorReducerConstructor(
val ordinalCompOp: FiltersScope.ComparisonType,
val order: SelectQuery.Order
) {
abstract fun <sRT, sDT : DatabaseType<sRT>> setup(
c: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>,
o: IntermediateColumn<UByte, U8, Query<sRT, sDT>>,
s: QueryParam<UByte, U8, Query<sRT, sDT>>
)
}
private class Inc private constructor(context: Reducer.Constructor.Scope<Inc>) : Reducer.Action<Inc> {
private val C_Ordinal = context.bidirectionalColumn("last_ordinal", context.types.U8)
override fun calculate(acc: OutputRow<Inc>, row: OutputRow<Inc>, newAcc: InputRow<Inc>) {
val new = row[this.C_Ordinal]
if (acc[this.C_Ordinal].toUInt() + 1u == new.toUInt())
newAcc[this.C_Ordinal] = new
}
companion object : _OrdinalSelectorReducerConstructor(FiltersScope.ComparisonType.GREATER, SelectQuery.Order.ASC), Reducer.Constructor<Inc> {
override fun createReducer(context: Reducer.Constructor.Scope<Inc>) = Inc(context)
override fun <sRT, sDT : DatabaseType<sRT>> setup(
c: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>,
o: IntermediateColumn<UByte, U8, Query<sRT, sDT>>,
s: QueryParam<UByte, U8, Query<sRT, sDT>>
) {
c.reduceRows(c.createReducer(this)) { l -> l.linkAndInitialize(l.uExt.C_Ordinal, o, s) }
}
}
object Inclusive : _OrdinalSelectorReducerConstructor(FiltersScope.ComparisonType.GREATER_OR_EQUALS, SelectQuery.Order.ASC) {
override fun <sRT, sDT : DatabaseType<sRT>> setup(
c: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>,
o: IntermediateColumn<UByte, U8, Query<sRT, sDT>>,
s: QueryParam<UByte, U8, Query<sRT, sDT>>
) {
c.reduceRows(c.createReducer(Inc)) { l -> l.linkAndInitialize(l.uExt.C_Ordinal, o, 0u) }
}
}
}
private class Dec private constructor(context: Reducer.Constructor.Scope<Dec>) : Reducer.Action<Dec> {
private val C_Ordinal = context.bidirectionalColumn("last_ordinal", context.types.U8)
override fun calculate(acc: OutputRow<Dec>, row: OutputRow<Dec>, newAcc: InputRow<Dec>) {
val new = row[this.C_Ordinal]
if (acc[this.C_Ordinal].toUInt() - 1u == new.toUInt())
newAcc[this.C_Ordinal] = new
}
companion object : _OrdinalSelectorReducerConstructor(FiltersScope.ComparisonType.LESS, SelectQuery.Order.DESC), Reducer.Constructor<Dec> {
override fun createReducer(context: Reducer.Constructor.Scope<Dec>) = Dec(context)
override fun <sRT, sDT : DatabaseType<sRT>> setup(
c: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>,
o: IntermediateColumn<UByte, U8, Query<sRT, sDT>>,
s: QueryParam<UByte, U8, Query<sRT, sDT>>
) {
c.reduceRows(c.createReducer(this)) { l -> l.linkAndInitialize(l.uExt.C_Ordinal, o, s) }
}
}
}
private class Query<sRT, sDT : DatabaseType<sRT>> private constructor(
context: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>,
reducer: _OrdinalSelectorReducerConstructor,
selectorColumn: (T_User2Queue) -> Column<sRT, sDT, T_User2Queue>
) {
val P_Ordinal = context.queryParam("ordinal", context.src.uExt.C_Ordinal.type)
val _P_Selector = context.queryParam("_selector", selectorColumn(context.src.uExt).type)
val C_Ordinal: Column<UByte, U8, Query<sRT, sDT>>
init {
val ordinalColumn = context.selectColumnFromSubquery(context.src.uExt.C_Ordinal)
this.C_Ordinal = context.returnColumn("ordinal", ordinalColumn)
reducer.setup(context, ordinalColumn, this.P_Ordinal)
context.filters.compareWithParam(ordinalColumn, reducer.ordinalCompOp, this.P_Ordinal)
context.orderBy(reducer.order, ordinalColumn)
context.filters.compareWithParam(context.selectColumnFromSubquery(selectorColumn(context.src.uExt)), FiltersScope.ComparisonType.EQUALS, this._P_Selector)
}
class Constructor<sRT, sDT : DatabaseType<sRT>>(
override val source: _Selectable<T_User2Queue>,
private val reducer: _OrdinalSelectorReducerConstructor,
private val selectorColumn: (T_User2Queue) -> Column<sRT, sDT, T_User2Queue>
) : SelectQuery.Reducing.Constructor<Query<sRT, sDT>, T_User2Queue> {
override fun createSelectWithReduce(context: SelectQuery.Reducing.Constructor.Scope<Query<sRT, sDT>, T_User2Queue>) =
Query(context, this.reducer, this.selectorColumn)
}
}
}

View File

@ -0,0 +1,66 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.db.serdha0.api.misc.FiltersScope
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class S_FindNeighbourQueue(private val module: Module<M_V0>) : _Query.Constructor<S_FindNeighbourQueue.Queries> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope) =
Queries(
getOrdinal = outQueries.select(S_GetQueueOrdinal.Constructor(this.module.uExt.queues)),
prev = outQueries.select(Query.Constructor(this.module.uExt.queues, SelectQuery.Order.DESC, FiltersScope.ComparisonType.LESS)),
next = outQueries.select(Query.Constructor(this.module.uExt.queues, SelectQuery.Order.ASC, FiltersScope.ComparisonType.GREATER))
)
class Queries(
val getOrdinal: SelectQuery.Simple<S_GetQueueOrdinal>,
val prev: SelectQuery.Simple<Query>,
val next: SelectQuery.Simple<Query>
)
class S_GetQueueOrdinal(
context: SelectQuery.Simple.Constructor.Scope<S_GetQueueOrdinal, T_Queues>
) {
val P_RowId = context.queryParam("row_id", context.src.uExt.C_RowId.type)
val C_Ordinal = context.returnColumn("ordinal", context.selectColumnFromSubquery(context.src.uExt.C_Ordinal))
class Constructor(override val source: _Selectable<T_Queues>) : SelectQuery.Simple.Constructor<S_GetQueueOrdinal, T_Queues> {
override fun createSelect(context: SelectQuery.Simple.Constructor.Scope<S_GetQueueOrdinal, T_Queues>) = S_GetQueueOrdinal(context)
}
}
class Query private constructor(
context: SelectQuery.Simple.Constructor.Scope<Query, T_Queues>,
order: SelectQuery.Order,
operator: FiltersScope.ComparisonType
) {
val P_QueueSet = context.queryParam("queue_set", context.src.uExt.C_QueueSet.type)
val P_OldOrdinal = context.queryParam("old_ordinal", context.src.uExt.C_Ordinal.type)
val C_NewQueue = context.returnColumn("new_queue", context.selectColumnFromSubquery(context.src.uExt.C_RowId))
init {
val ordinalColumn = context.selectColumnFromSubquery(context.src.uExt.C_Ordinal)
context.filters.compareWithParam(
column = ordinalColumn,
param = this.P_OldOrdinal,
operator = operator
)
context.orderBy(order, ordinalColumn)
}
class Constructor(
override val source: _Selectable<T_Queues>,
private val order: SelectQuery.Order,
private val operator: FiltersScope.ComparisonType
) : SelectQuery.Simple.Constructor<Query, T_Queues> {
override fun createSelect(context: SelectQuery.Simple.Constructor.Scope<Query, T_Queues>) =
Query(context, this.order, this.operator)
}
}
}

View File

@ -0,0 +1,94 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.FoundQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Chats
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.db.serdha0.api.misc.Column
import ru.landgrafhomyak.db.serdha0.api.misc.FiltersScope
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class S_FindQueueSet(private val module: Module<M_V0>) : _Query.Constructor<S_FindQueueSet.Queries> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope) =
Queries(
byMessage = outQueries.selectWithJoin(
S_FindQueueSetByMessage.Constructor(
this.module.uExt.queueSets,
internalQueries.select(S_FindChat.Constructor(this.module.uExt.chats))
)
),
byId = outQueries.select(S_FindQueueSetById.Constructor(this.module.uExt.queueSets))
)
class Queries(
val byMessage: SelectQuery.WithJoin<S_FindQueueSetByMessage>,
val byId: SelectQuery.Simple<S_FindQueueSetById>
)
class S_FindChat private constructor(context: SelectQuery.Simple.Constructor.Scope<S_FindChat, T_Chats>) {
val P_TgCid = context.queryParam("tg_cid", context.src.uExt.C_TgCid.type)
val C_RowId = context.returnColumn("row_id", context.selectColumnFromSubquery(context.src.uExt.C_RowId))
init {
context.filters.compareWithParam(
column = context.selectColumnFromSubquery(context.src.uExt.C_TgCid),
param = this.P_TgCid,
operator = FiltersScope.ComparisonType.EQUALS
)
}
class Constructor(override val source: _Selectable<T_Chats>) : SelectQuery.Simple.Constructor<S_FindChat, T_Chats> {
override fun createSelect(context: SelectQuery.Simple.Constructor.Scope<S_FindChat, T_Chats>) =
S_FindChat(context)
}
}
class S_FindQueueSetByMessage private constructor(context: SelectQuery.WithJoin.Constructor.Scope<S_FindQueueSetByMessage, T_QueueSets, S_FindChat>) : FoundQueue.QueueSetRow<S_FindQueueSetByMessage> {
val P_TgCid = context.queryParam("tg_cid", context.rsq.uExt.P_TgCid.type)
val P_TgMid = context.queryParam("tg_mid", context.lsq.uExt.C_TgMid.type)
override val C_QsRowId = context.returnColumn("row_id", context.selectColumnFromLeft(context.lsq.uExt.C_RowId))
override val C_QsName = context.returnColumn("name", context.selectColumnFromLeft(context.lsq.uExt.C_Name))
override val C_QsIsOpen = context.returnColumn("is_open", context.selectColumnFromLeft(context.lsq.uExt.C_IsOpen))
init {
context.rightSubqueryParams.redirect(context.rsq.uExt.P_TgCid, this.P_TgCid)
}
class Constructor(override val left: _Selectable<T_QueueSets>, override val right: _Selectable<S_FindChat>) : SelectQuery.WithJoin.Constructor<S_FindQueueSetByMessage, T_QueueSets, S_FindChat> {
override val joinType: SelectQuery.JoinType = SelectQuery.JoinType(
SelectQuery.JoinType.LeftNull.NULL_NOT_EXPECTED,
SelectQuery.JoinType.Join.LEFT_TO_FIRST_RIGHT
)
override val referenceColumn: Column<*, *, T_QueueSets> = this.left.uExt.C_Chat
override val targetColumn: Column<*, *, S_FindChat> = this.right.uExt.C_RowId
override fun createSelectWithJoin(context: SelectQuery.WithJoin.Constructor.Scope<S_FindQueueSetByMessage, T_QueueSets, S_FindChat>) =
S_FindQueueSetByMessage(context)
}
}
class S_FindQueueSetById private constructor(context: SelectQuery.Simple.Constructor.Scope<S_FindQueueSetById, T_QueueSets>) : FoundQueue.QueueSetRow<S_FindQueueSetById> {
val P_RowId = context.queryParam("tg_cid", context.src.uExt.C_RowId.type)
override val C_QsRowId = context.returnColumn("row_id", context.selectColumnFromSubquery(context.src.uExt.C_RowId))
override val C_QsName = context.returnColumn("name", context.selectColumnFromSubquery(context.src.uExt.C_Name))
override val C_QsIsOpen = context.returnColumn("is_open", context.selectColumnFromSubquery(context.src.uExt.C_IsOpen))
init {
context.filters.compareWithParam(
column = context.selectColumnFromSubquery(context.src.uExt.C_RowId),
param = this.P_RowId,
operator = FiltersScope.ComparisonType.EQUALS
)
}
class Constructor(override val source: _Selectable<T_QueueSets>) : SelectQuery.Simple.Constructor<S_FindQueueSetById, T_QueueSets> {
override fun createSelect(context: SelectQuery.Simple.Constructor.Scope<S_FindQueueSetById, T_QueueSets>) =
S_FindQueueSetById(context)
}
}
}

View File

@ -0,0 +1,54 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.FoundUserInQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.db.serdha0.api.misc.FiltersScope
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class S_FindUserInQueue(private val module: Module<M_V0>) : _Query.Constructor<SelectQuery.WithJoin<S_FindUserInQueue.Query>> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope) =
outQueries.selectWithJoin(
Query.Constructor(
internalQueries(U_GetUser(this.module)),
this.module.uExt.user2queue
)
)
class Query private constructor(context: SelectQuery.WithJoin.Constructor.Scope<Query, U_GetUser, T_User2Queue>) : FoundUserInQueue.UserInQueueRow<Query> {
val P_TgUid = context.queryParam("tg_uid", context.lsq.uExt.P_TgUid.type)
val P_UDisplayName = context.queryParam("u_display_name", context.lsq.uExt.P_DisplayName.type)
val P_QueueSet = context.queryParam("queue_set", context.rsq.uExt.C_QueueSet.type)
override val C_RowId = context.returnColumn("_row_id", context.selectColumnFromRight(context.rsq.uExt.C_RowId))
override val C_URowId = context.returnColumn("u_row_id", context.selectColumnFromLeft(context.lsq.uExt.C_RowId))
override val C_UDisplayName = context.returnColumn("u_display_name", context.selectColumnFromLeft(context.lsq.uExt.C_DisplayName))
override val C_QRowId = context.returnColumn("queue", context.selectColumnFromRight(context.rsq.uExt.C_Queue))
override val C_Ordinal = context.returnColumn("queue", context.selectColumnFromRightAsNullable(context.rsq.uExt.C_Ordinal))
init {
context.leftSubqueryParams.redirect(context.lsq.uExt.P_TgUid, this.P_TgUid)
context.leftSubqueryParams.redirect(context.lsq.uExt.P_DisplayName, this.P_UDisplayName)
context.filters.compareWithParam(context.selectColumnFromRight(context.rsq.uExt.C_QueueSet), FiltersScope.ComparisonType.EQUALS, this.P_QueueSet)
}
class Constructor(
override val left: _Selectable<U_GetUser>,
override val right: _Selectable<T_User2Queue>
) : SelectQuery.WithJoin.Constructor<Query, U_GetUser, T_User2Queue> {
override val joinType = SelectQuery.JoinType(
leftNull = SelectQuery.JoinType.LeftNull.NULL_NOT_EXPECTED,
join = SelectQuery.JoinType.Join.LEFT_FOR_EACH_RIGHT_OR_TO_NULL
)
override val referenceColumn = this.left.uExt.C_RowId
override val targetColumn = this.right.uExt.C_QueueSet
override fun createSelectWithJoin(context: SelectQuery.WithJoin.Constructor.Scope<Query, U_GetUser, T_User2Queue>) =
Query(context)
}
}
}

View File

@ -0,0 +1,31 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.db.serdha0.api.misc.FiltersScope
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.SelectQuery
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class S_FirstQueueInSet private constructor(context: SelectQuery.Simple.Constructor.Scope<S_FirstQueueInSet, T_Queues>) {
val P_QueueSet = context.queryParam("queue_set", context.src.uExt.C_QueueSet.type)
val C_Queue = context.returnColumn("queue", context.selectColumnFromSubquery(context.src.uExt.C_RowId))
init {
context.filters.compareWithParam(context.selectColumnFromSubquery(context.src.uExt.C_QueueSet), FiltersScope.ComparisonType.EQUALS, this.P_QueueSet)
context.orderBy(SelectQuery.Order.ASC, context.selectColumnFromSubquery(context.src.uExt.C_Ordinal))
context.limit = 1u
}
private class _Constructor(
override val source: _Selectable<T_Queues>
) : SelectQuery.Simple.Constructor<S_FirstQueueInSet, T_Queues> {
override fun createSelect(context: SelectQuery.Simple.Constructor.Scope<S_FirstQueueInSet, T_Queues>) = S_FirstQueueInSet(context)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>) : SelectQuery.Simple.Constructor<S_FirstQueueInSet, T_Queues> = _Constructor(module.uExt.queues)
}
}

View File

@ -0,0 +1,49 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.FoundQueue
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.db.serdha0.api.misc._Selectable
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.UpdateQuery
import ru.landgrafhomyak.db.serdha0.api.queries._Query
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class U_ChangeQueueState(private val module: Module<M_V0>) : _Query.Constructor<UpdateQuery.FromSubquery<U_ChangeQueueState.Query>> {
override fun createQuery(internalQueries: _Query.Constructor.Scope, outQueries: _Query.Constructor.Scope) =
outQueries.updateFromSubquery(
Query.Constructor(
this.module.uExt.queueSets,
internalQueries(S_FindQueueSet(this.module)).byMessage
)
)
class Query private constructor(context: UpdateQuery.FromSubquery.Constructor.Scope<Query, T_QueueSets, S_FindQueueSet.S_FindQueueSetByMessage>) : FoundQueue.QueueSetRow<Query> {
val P_TgCid = context.queryParam("tg_cid", context.src.uExt.P_TgCid.type)
val P_TgMid = context.queryParam("tg_mid", context.src.uExt.P_TgMid.type)
val P_NewState = context.queryParam("new_state", context.types.BOOLEAN)
val C_OldIsOpen = context.returnOldValue("old_state", context.tt.uExt.C_IsOpen)
override val C_QsRowId = context.returnNewValue("row_id", context.tt.uExt.C_RowId)
override val C_QsName = context.returnNewValue("name", context.tt.uExt.C_Name)
override val C_QsIsOpen = context.returnNewValue("new_state", context.tt.uExt.C_IsOpen)
init {
context.selectorParams.redirect(context.src.uExt.P_TgCid, this.P_TgCid)
context.selectorParams.redirect(context.src.uExt.P_TgMid, this.P_TgMid)
context.selectorColumn = context.src.uExt.C_QsRowId
context.ifNoRowSkip()
}
class Constructor(
override val targetTable: Table<T_QueueSets, *>,
override val selector: _Selectable<S_FindQueueSet.S_FindQueueSetByMessage>
) : UpdateQuery.FromSubquery.Constructor<Query, T_QueueSets, S_FindQueueSet.S_FindQueueSetByMessage> {
override fun createUpdateFromSubqueryWithReturning(context: UpdateQuery.FromSubquery.Constructor.Scope<Query, T_QueueSets, S_FindQueueSet.S_FindQueueSetByMessage>) =
Query(context)
}
}
}

View File

@ -0,0 +1,39 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.STRING
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U64
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema._temp.U8
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_QueueSets
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Queues
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_Users
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.InsertQuery
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
class U_GetUser private constructor(context: InsertQuery.SingleRow.Constructor.Scope<U_GetUser, T_Users>) {
val P_TgUid = context.queryParam("tg_uid", context.types.U64)
val P_DisplayName = context.queryParam("display_name", context.types.STRING)
val C_RowId = context.returnInsertedValue("row_id", context.tt.uExt.C_RowId)
val C_DisplayName = context.returnInsertedValue("display_name", context.tt.uExt.C_DisplayName)
init {
context.insertParam(context.tt.uExt.C_TgUid, this.P_TgUid)
context.insertParam(context.tt.uExt.C_DisplayName, this.P_DisplayName)
context.onConflictUpdate(context.tt.uExt.U_TgUid) { upd ->
upd.overrideColumn(context.tt.uExt.C_DisplayName)
}
}
private class _Constructor(private val module: Module<M_V0>) : InsertQuery.SingleRow.Constructor<U_GetUser, T_Users> {
override val targetTable: Table<T_Users, *> = this.module.uExt.users
override fun createInsertSingleRowWithReturning(context: InsertQuery.SingleRow.Constructor.Scope<U_GetUser, T_Users>) =
U_GetUser(context)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>): InsertQuery.SingleRow.Constructor<U_GetUser, T_Users> = _Constructor(module)
}
}

View File

@ -0,0 +1,30 @@
package ru.landgrafhomyak.bgtu.db0.storage.serdha.queries
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.M_V0
import ru.landgrafhomyak.bgtu.db0.storage.serdha.schema.v0.T_User2Queue
import ru.landgrafhomyak.db.serdha0.api.module.Module
import ru.landgrafhomyak.db.serdha0.api.queries.InsertQuery
import ru.landgrafhomyak.db.serdha0.api.queries.UpdateQuery
import ru.landgrafhomyak.db.serdha0.api.table.Table
@Suppress("ClassName", "PropertyName", "MemberVisibilityCanBePrivate")
internal class U_MoveUserInQueue private constructor(context: UpdateQuery.SingleRow.Constructor.Scope<U_MoveUserInQueue, T_User2Queue>) {
val P_RowId = context.rowToUpdate
val P_NewQueue = context.queryParam("queue", context.tt.uExt.C_Queue.type)
val P_NewOrdinal = context.queryParam("ordinal", context.tt.uExt.C_Ordinal.type)
init {
context.updateColumnWithParam(context.tt.uExt.C_Queue, this.P_NewQueue)
context.updateColumnWithParam(context.tt.uExt.C_Ordinal, this.P_NewOrdinal)
}
private class _Constructor(
override val targetTable: Table<T_User2Queue, *>
) : UpdateQuery.SingleRow.Constructor<U_MoveUserInQueue, T_User2Queue> {
override fun createUpdateSingleWithReturning(context: UpdateQuery.SingleRow.Constructor.Scope<U_MoveUserInQueue, T_User2Queue>) = U_MoveUserInQueue(context)
}
companion object Constructor {
operator fun invoke(module: Module<M_V0>): UpdateQuery.SingleRow.Constructor<U_MoveUserInQueue, T_User2Queue> = _Constructor(module.uExt.user2queue)
}
}