Row consumers now aren't 'fun interfaces' to allow using contracts in functions with lambdas

This commit is contained in:
Andrew Golovashevich 2025-02-25 14:57:41 +03:00
parent 9b48f6d2a3
commit d6ecd1fb4b
5 changed files with 289 additions and 108 deletions

View File

@ -2,6 +2,6 @@ package ru.landgrafhomyak.db.serdha0.user_commons.executors
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
public fun interface RowConsumer0<qUE : Any, R> {
public interface RowConsumer0<qUE : Any, R> {
public fun transformRow(row: OutputRow<qUE>): R
}

View File

@ -2,6 +2,6 @@ package ru.landgrafhomyak.db.serdha0.user_commons.executors
import ru.landgrafhomyak.db.serdha0.api.runtime.OutputRow
public fun interface RowConsumer1<qUE : Any, R> {
public interface RowConsumer1<qUE : Any, R> {
public fun transformRow(row: OutputRow<qUE>, index: Int): R
}

View File

@ -4,9 +4,12 @@
package ru.landgrafhomyak.db.serdha0.user_commons.executors
import kotlin.contracts.InvocationKind
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.OutputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
public class ExpectedOneRowException : Error("Expected at least one row, but table is empty")
@ -15,18 +18,45 @@ public class TooManyRowsException : Error("Expected exactly one row, but got mor
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrError(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: RowConsumer0<qUE, R>
result: (OutputRow<qUE>) -> R
): R {
contract {
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
if (!oRow._next())
throw ExpectedOneRowException()
val ret = result.transformRow(oRow)
if (oRow._next())
throw TooManyRowsException()
return ret
_safeAutoClose(onSuccess = { if (oRow._next()) throw TooManyRowsException() }) {
return result(oRow)
}
}
)
}
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrError(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: RowConsumer0<qUE, R>
): R = this.selectExactlyOneOrError(compiledQuery, params, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrError(
compiledQuery: _Query.Void2Table<qUE>,
result: (OutputRow<qUE>) -> R
): R {
contract {
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
if (!oRow._next())
throw ExpectedOneRowException()
_safeAutoClose(onSuccess = { if (oRow._next()) throw TooManyRowsException() }) {
return result(oRow)
}
}
)
}
@ -34,16 +64,25 @@ public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrError(
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrError(
compiledQuery: _Query.Void2Table<qUE>,
result: RowConsumer0<qUE, R>
): R {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): R = this.selectExactlyOneOrError(compiledQuery, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrNull(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: (OutputRow<qUE>) -> R
): R? {
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
if (!oRow._next())
throw ExpectedOneRowException()
val ret = result.transformRow(oRow)
if (oRow._next())
throw TooManyRowsException()
return ret
return null
_safeAutoClose(onSuccess = { if (oRow._next()) throw TooManyRowsException() }) {
return result(oRow)
}
}
)
}
@ -52,17 +91,23 @@ public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrNull(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: RowConsumer0<qUE, R>
): R? = this.selectExactlyOneOrNull(compiledQuery, params, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrNull(
compiledQuery: _Query.Void2Table<qUE>,
result: (OutputRow<qUE>) -> R
): R? {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
if (!oRow._next())
return null
val ret = result.transformRow(oRow)
if (oRow._next())
throw TooManyRowsException()
return ret
_safeAutoClose(onSuccess = { if (oRow._next()) throw TooManyRowsException() }) {
return result(oRow)
}
}
)
}
@ -70,16 +115,23 @@ public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrNull(
public suspend inline fun <qUE : Any, R> Transaction.selectExactlyOneOrNull(
compiledQuery: _Query.Void2Table<qUE>,
result: RowConsumer0<qUE, R>
): R? {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): R? = this.selectExactlyOneOrNull(compiledQuery, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrError(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: (OutputRow<qUE>) -> R
): R {
contract {
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
if (!oRow._next())
return null
val ret = result.transformRow(oRow)
if (oRow._next())
throw TooManyRowsException()
return ret
throw ExpectedOneRowException()
return result(oRow)
}
)
}
@ -88,14 +140,21 @@ public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrError(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: RowConsumer0<qUE, R>
): R = this.selectFirstOrError(compiledQuery, params, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrError(
compiledQuery: _Query.Void2Table<qUE>,
result: (OutputRow<qUE>) -> R
): R {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(result, InvocationKind.EXACTLY_ONCE)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
if (!oRow._next())
throw ExpectedOneRowException()
return result.transformRow(oRow)
return result(oRow)
}
)
}
@ -103,13 +162,23 @@ public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrError(
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrError(
compiledQuery: _Query.Void2Table<qUE>,
result: RowConsumer0<qUE, R>
): R {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): R = this.selectFirstOrError(compiledQuery, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrNull(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: (OutputRow<qUE>) -> R
): R? {
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
if (!oRow._next())
throw ExpectedOneRowException()
return result.transformRow(oRow)
return null
return result(oRow)
}
)
}
@ -118,14 +187,21 @@ public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrNull(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
result: RowConsumer0<qUE, R>
): R? = this.selectFirstOrNull(compiledQuery, params, result::transformRow)
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrNull(
compiledQuery: _Query.Void2Table<qUE>,
result: (OutputRow<qUE>) -> R
): R? {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
if (!oRow._next())
return null
return result.transformRow(oRow)
return result(oRow)
}
)
}
@ -133,13 +209,4 @@ public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrNull(
public suspend inline fun <qUE : Any, R> Transaction.selectFirstOrNull(
compiledQuery: _Query.Void2Table<qUE>,
result: RowConsumer0<qUE, R>
): R? {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
if (!oRow._next())
return null
return result.transformRow(oRow)
}
)
}
): R? = this.selectFirstOrNull(compiledQuery, result::transformRow)

View File

@ -4,22 +4,50 @@
package ru.landgrafhomyak.db.serdha0.user_commons.executors
import kotlin.contracts.InvocationKind
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.OutputRow
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
public suspend inline fun <qUE : Any> Transaction.select(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
transform: RowConsumer0<qUE, Unit>
transform: (OutputRow<qUE>) -> Unit
) {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
while (oRow._next())
transform.transformRow(oRow)
transform(oRow)
}
)
}
public suspend inline fun <qUE : Any> Transaction.select(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
transform: RowConsumer0<qUE, Unit>
): Unit = this.select(compiledQuery, params, transform::transformRow)
public suspend inline fun <qUE : Any> Transaction.select(
compiledQuery: _Query.Void2Table<qUE>,
transform: (OutputRow<qUE>) -> Unit
) {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
while (oRow._next())
transform(oRow)
}
)
}
@ -27,12 +55,24 @@ public suspend inline fun <qUE : Any> Transaction.select(
public suspend inline fun <qUE : Any> Transaction.select(
compiledQuery: _Query.Void2Table<qUE>,
transform: RowConsumer0<qUE, Unit>
) {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): Unit = this.select(compiledQuery, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRows(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
transform: (OutputRow<qUE>) -> E
): List<E> {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
val dst = ArrayList<E>()
while (oRow._next())
transform.transformRow(oRow)
dst.add(transform(oRow))
return dst
}
)
}
@ -41,14 +81,21 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRows(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
transform: RowConsumer0<qUE, E>
): List<E> = this.mapRows(compiledQuery, params, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRows(
compiledQuery: _Query.Void2Table<qUE>,
transform: (OutputRow<qUE>) -> E
): List<E> {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
val dst = ArrayList<E>()
while (oRow._next())
dst.add(transform.transformRow(oRow))
dst.add(transform(oRow))
return dst
}
)
@ -57,13 +104,25 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRows(
public suspend inline fun <qUE : Any, E> Transaction.mapRows(
compiledQuery: _Query.Void2Table<qUE>,
transform: RowConsumer0<qUE, E>
): List<E> = this.mapRows(compiledQuery, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRowsIndexed(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
firstIndex: Int = 0,
transform: (OutputRow<qUE>, Int) -> E
): List<E> {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
val dst = ArrayList<E>()
var i = firstIndex
while (oRow._next())
dst.add(transform.transformRow(oRow))
dst.add(transform(oRow, i++))
return dst
}
)
@ -74,15 +133,23 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRowsIndexed(
params: RowProducer0<qUE>,
firstIndex: Int = 0,
transform: RowConsumer1<qUE, E>
): List<E> = this.mapRowsIndexed(compiledQuery, params, firstIndex, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRowsIndexed(
compiledQuery: _Query.Void2Table<qUE>,
firstIndex: Int = 0,
transform: (OutputRow<qUE>, Int) -> E
): List<E> {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
val dst = ArrayList<E>()
var i = firstIndex
while (oRow._next())
dst.add(transform.transformRow(oRow, i++))
dst.add(transform(oRow, i++))
return dst
}
)
@ -92,14 +159,23 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRowsIndexed(
compiledQuery: _Query.Void2Table<qUE>,
firstIndex: Int = 0,
transform: RowConsumer1<qUE, E>
): List<E> {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): List<E> = this.mapRowsIndexed(compiledQuery, firstIndex, transform::transformRow)
public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.mapRowsTo(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
dst: C,
transform: (OutputRow<qUE>) -> E
): C {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
val dst = ArrayList<E>()
var i = firstIndex
while (oRow._next())
dst.add(transform.transformRow(oRow, i++))
dst.add(transform(oRow))
return dst
}
)
@ -110,13 +186,21 @@ public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.m
params: RowProducer0<qUE>,
dst: C,
transform: RowConsumer0<qUE, E>
): C = this.mapRowsTo(compiledQuery, params, dst, transform::transformRow)
public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.mapRowsTo(
compiledQuery: _Query.Void2Table<qUE>,
dst: C,
transform: (OutputRow<qUE>) -> E
): C {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
while (oRow._next())
dst.add(transform.transformRow(oRow))
dst.add(transform(oRow))
return dst
}
)
@ -126,12 +210,24 @@ public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.m
compiledQuery: _Query.Void2Table<qUE>,
dst: C,
transform: RowConsumer0<qUE, E>
): C = this.mapRowsTo(compiledQuery, dst, transform::transformRow)
public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.mapRowsIndexedTo(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
dst: C, firstIndex: Int = 0,
transform: (OutputRow<qUE>, Int) -> E
): C {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
var i = firstIndex
while (oRow._next())
dst.add(transform.transformRow(oRow))
dst.add(transform(oRow, i++))
return dst
}
)
@ -142,14 +238,22 @@ public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.m
params: RowProducer0<qUE>,
dst: C, firstIndex: Int = 0,
transform: RowConsumer1<qUE, E>
): C = this.mapRowsIndexedTo(compiledQuery, params, dst, firstIndex, transform::transformRow)
public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.mapRowsIndexedTo(
compiledQuery: _Query.Void2Table<qUE>,
dst: C, firstIndex: Int = 0,
transform: (OutputRow<qUE>, Int) -> E
): C {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
var i = firstIndex
while (oRow._next())
dst.add(transform.transformRow(oRow, i++))
dst.add(transform(oRow, i++))
return dst
}
)
@ -159,13 +263,24 @@ public suspend inline fun <qUE : Any, E, C : MutableCollection<E>> Transaction.m
compiledQuery: _Query.Void2Table<qUE>,
dst: C, firstIndex: Int = 0,
transform: RowConsumer1<qUE, E>
): C {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
): C = this.mapRowsIndexedTo(compiledQuery, dst, firstIndex, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRowsTo(
compiledQuery: _Query.Params2Table<qUE>,
params: RowProducer0<qUE>,
dst: Array<E>, dstOffset: Int = 0,
transform: (OutputRow<qUE>) -> E
): Array<E> {
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
outputAction = { oRow ->
var i = firstIndex
var i = dstOffset
while (oRow._next())
dst.add(transform.transformRow(oRow, i++))
dst[i++] = transform(oRow)
return dst
}
)
@ -176,14 +291,22 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRowsTo(
params: RowProducer0<qUE>,
dst: Array<E>, dstOffset: Int = 0,
transform: RowConsumer0<qUE, E>
): Array<E> = this.mapRowsTo(compiledQuery, params, dst, dstOffset, transform::transformRow)
public suspend inline fun <qUE : Any, E> Transaction.mapRowsTo(
compiledQuery: _Query.Void2Table<qUE>,
dst: Array<E>, dstOffset: Int = 0,
transform: (OutputRow<qUE>) -> E
): Array<E> {
_safeAutoClose_IO(
iRow = this._executeQuery(compiledQuery),
inputAction = params::initializeRow,
contract {
callsInPlace(transform, InvocationKind.UNKNOWN)
}
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
var i = dstOffset
while (oRow._next())
dst[i++] = transform.transformRow(oRow)
dst[i++] = transform(oRow)
return dst
}
)
@ -193,14 +316,4 @@ public suspend inline fun <qUE : Any, E> Transaction.mapRowsTo(
compiledQuery: _Query.Void2Table<qUE>,
dst: Array<E>, dstOffset: Int = 0,
transform: RowConsumer0<qUE, E>
): Array<E> {
_safeAutoClose_O(
oRow = this._executeQuery(compiledQuery),
outputAction = { oRow ->
var i = dstOffset
while (oRow._next())
dst[i++] = transform.transformRow(oRow)
return dst
}
)
}
): Array<E> = this.mapRowsTo(compiledQuery, dst, dstOffset, transform::transformRow)

View File

@ -1,9 +1,10 @@
@file:OptIn(LowLevelApi::class)
@file:JvmName("_TransactionsKt")
package ru.landgrafhomyak.db.serdha0.user_commons.executors
import kotlin.jvm.JvmName
import ru.landgrafhomyak.db.serdha0.api.LowLevelApi
import ru.landgrafhomyak.db.serdha0.api.runtime.Executor
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction