From d6ecd1fb4bc0ca664358de977f37901ed0cc41c4 Mon Sep 17 00:00:00 2001
From: Andrew Golovashevich <landgrafhomyak@gmail.com>
Date: Tue, 25 Feb 2025 14:57:41 +0300
Subject: [PATCH] Row consumers now aren't 'fun interfaces' to allow using
 contracts in functions with lambdas

---
 .../user_commons/executors/RowConsumer0.kt    |   2 +-
 .../user_commons/executors/RowConsumer1.kt    |   2 +-
 .../serdha0/user_commons/executors/row2row.kt | 169 ++++++++++----
 .../user_commons/executors/row2table.kt       | 221 +++++++++++++-----
 .../user_commons/executors/transaction.kt     |   3 +-
 5 files changed, 289 insertions(+), 108 deletions(-)

diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer0.kt b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer0.kt
index 6baba1d..d336a55 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer0.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer0.kt
@@ -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
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer1.kt b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer1.kt
index 2c54ae0..46e2806 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer1.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/RowConsumer1.kt
@@ -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
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2row.kt b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2row.kt
index a4e9ddf..bf5ebb4 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2row.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2row.kt
@@ -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)
-		}
-	)
-}
\ No newline at end of file
+): R? = this.selectFirstOrNull(compiledQuery, result::transformRow)
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2table.kt b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2table.kt
index fc299e6..347429e 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2table.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/row2table.kt
@@ -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
-		}
-	)
-}
\ No newline at end of file
+): Array<E> = this.mapRowsTo(compiledQuery, dst, dstOffset, transform::transformRow)
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/transaction.kt b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/transaction.kt
index 72503a2..1d33821 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/transaction.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/db/serdha0/user_commons/executors/transaction.kt
@@ -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