From ae1430b6961e26c20938b3edd4b068b39ee5dc2d Mon Sep 17 00:00:00 2001
From: Andrew Golovashevich <landgrafhomyak@gmail.com>
Date: Thu, 28 Nov 2024 21:33:42 +0300
Subject: [PATCH] DELETE, fixes, auto-transactions

---
 .../serdha/api/v0/Expression.kt               |   7 +-
 .../serdha/api/v0/ddl/Module.kt               |   4 +
 .../serdha/api/v0/ddl/ModuleModifyingRound.kt |  48 ++-
 .../serdha/api/v0/ddl/TableCreator.kt         |   6 +
 .../serdha/api/v0/dml/Delete.kt               |   5 +
 .../serdha/api/v0/dml/DeleteCreator.kt        |  16 +
 .../serdha/api/v0/dml/InsertCreator.kt        |   2 +-
 .../serdha/api/v0/dml/SelectCreator.kt        |   3 +
 .../serdha/api/v0/dml/SelectedColumn.kt       |   2 +-
 .../serdha/api/v0/dml/UpdateCreator.kt        |   4 +-
 .../serdha/api/v0/runtime/ParametersSetter.kt |  23 +-
 .../api/v0/runtime/SynchronizedDatabase.kt    |  26 ++
 .../serdha/api/v0/runtime/Transaction.kt      |   5 +
 .../api/v0/runtime/transaction_methods.kt     | 379 +++++++++++++++++-
 14 files changed, 503 insertions(+), 27 deletions(-)
 create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/Delete.kt
 create mode 100644 src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/DeleteCreator.kt

diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/Expression.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/Expression.kt
index 3e1e962..3338173 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/Expression.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/Expression.kt
@@ -2,4 +2,9 @@ package ru.landgrafhomyak.serdha.api.v0
 
 import ru.landgrafhomyak.serdha.api.v0.ddl.ColumnType
 
-public interface Expression<RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>, OwnerBuilderUserWrapper : Any>
\ No newline at end of file
+public interface Expression<RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>, OwnerBuilderUserWrapper : Any> {
+	public class Equals<RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>, OwnerBuilderUserWrapper : Any>(
+		public val left: Expression<RuntimeType, DatabaseType, OwnerBuilderUserWrapper>,
+		public val right: Expression<RuntimeType, DatabaseType, OwnerBuilderUserWrapper>,
+	) : Expression<Boolean, ColumnType.BOOLEAN, OwnerBuilderUserWrapper>
+}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/Module.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/Module.kt
index 07164c6..969c1ab 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/Module.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/Module.kt
@@ -1,7 +1,11 @@
 package ru.landgrafhomyak.serdha.api.v0.ddl
 
+import ru.landgrafhomyak.serdha.api.v0.runtime.SynchronizedDatabase
+
 public interface Module<W : Any> {
 	public val wrapper: W
 
 	public val versionKey: String
+
+	public val ownerDatabase: SynchronizedDatabase<*>
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/ModuleModifyingRound.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/ModuleModifyingRound.kt
index 4d4bccb..fd49760 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/ModuleModifyingRound.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/ModuleModifyingRound.kt
@@ -1,5 +1,7 @@
 package ru.landgrafhomyak.serdha.api.v0.ddl
 
+import ru.landgrafhomyak.serdha.api.v0.dml.Delete
+import ru.landgrafhomyak.serdha.api.v0.dml.DeleteCreator
 import ru.landgrafhomyak.serdha.api.v0.dml.Insert
 import ru.landgrafhomyak.serdha.api.v0.dml.InsertCreator
 import ru.landgrafhomyak.serdha.api.v0.dml.Select
@@ -8,15 +10,19 @@ import ru.landgrafhomyak.serdha.api.v0.dml.Update
 import ru.landgrafhomyak.serdha.api.v0.dml.UpdateCreator
 
 public interface ModuleModifyingRound {
-	public fun <TableUserWrapper : Any> createTable(
-		namespace: Namespace,
-		name: String,
-		initializer: (TableCreator<TableUserWrapper>) -> TableUserWrapper
-	): Table<TableUserWrapper, Nothing>
+	public fun interface CreateTable<TableUserWrapper : Any> {
+		public fun createTable(creator: TableCreator<TableUserWrapper>): TableUserWrapper
+	}
+
+	public fun <TableUserWrapper : Any> createTable(namespace: Namespace, name: String, initializer: CreateTable<TableUserWrapper>): Table<TableUserWrapper, Nothing>
+
+	public fun interface UpdateTable<TableNewUserWrapper : Any, TableOldUserWrapper : Any> {
+		public fun updateTable(oldTable: Table<TableOldUserWrapper, *>, updater: TableUpdater<TableNewUserWrapper, TableOldUserWrapper>): TableNewUserWrapper
+	}
 
 	public fun <TableNewUserWrapper : Any, TableOldUserWrapper : Any> updateTable(
 		oldTable: Table<TableOldUserWrapper, *>,
-		initializer: (TableUpdater<TableNewUserWrapper, TableOldUserWrapper>) -> TableNewUserWrapper
+		initializer: UpdateTable<TableNewUserWrapper, TableOldUserWrapper>
 	): Table<TableNewUserWrapper, TableOldUserWrapper>
 
 	public fun <TableNewUserWrapper : Any, TableOldUserWrapper : Any> renameTable(
@@ -33,19 +39,39 @@ public interface ModuleModifyingRound {
 	public fun <TableNewUserWrapper : Any, TableOldUserWrapper : Any> updateAndRenameTable(
 		table: Table<TableOldUserWrapper, *>,
 		newName: String,
-		initializer: (TableUpdater<TableNewUserWrapper, TableOldUserWrapper>) -> TableNewUserWrapper
+		initializer: UpdateTable<TableNewUserWrapper, TableOldUserWrapper>
 	): Table<TableNewUserWrapper, TableOldUserWrapper>
 
 	public fun <TableNewUserWrapper : Any, TableOldUserWrapper : Any> updateAndRenameTable(
 		table: Table<TableNewUserWrapper, TableOldUserWrapper>,
 		newNamespace: Namespace,
 		newName: String,
-		initializer: (TableUpdater<TableNewUserWrapper, TableOldUserWrapper>) -> TableNewUserWrapper
+		initializer: UpdateTable<TableNewUserWrapper, TableOldUserWrapper>
 	): Table<TableNewUserWrapper, TableOldUserWrapper>
 
-	public fun <QueryUserWrapper : Any> createSelect(initializer: (SelectCreator<QueryUserWrapper>) -> QueryUserWrapper): Select<QueryUserWrapper>
-	public fun <TableUserWrapper : Any, QueryUserWrapper : Any> createInsert(table: Table<TableUserWrapper, *>, initializer: (InsertCreator<TableUserWrapper, QueryUserWrapper>) -> QueryUserWrapper): Insert<QueryUserWrapper>
-	public fun <TableUserWrapper : Any, QueryUserWrapper : Any> createUpdate(table: Table<TableUserWrapper, *>, initializer: (UpdateCreator<TableUserWrapper, QueryUserWrapper>) -> QueryUserWrapper): Update<QueryUserWrapper>
+	public fun interface CreateSelect<QueryUserWrapper : Any> {
+		public fun createSelect(creator: SelectCreator<QueryUserWrapper>): QueryUserWrapper
+	}
+
+	public fun <QueryUserWrapper : Any> createSelect(initializer: CreateSelect<QueryUserWrapper>): Select<QueryUserWrapper>
+
+	public fun interface CreateInsert<TableUserWrapper : Any, QueryUserWrapper : Any> {
+		public fun createInsert(table: Table<TableUserWrapper, *>, creator: InsertCreator<TableUserWrapper, QueryUserWrapper>): QueryUserWrapper
+	}
+
+	public fun <TableUserWrapper : Any, QueryUserWrapper : Any> createInsert(table: Table<TableUserWrapper, *>, initializer: CreateInsert<TableUserWrapper, QueryUserWrapper>): Insert<QueryUserWrapper>
+
+	public fun interface CreateUpdate<TableUserWrapper : Any, QueryUserWrapper : Any> {
+		public fun createUpdate(table: Table<TableUserWrapper, *>, creator: UpdateCreator<TableUserWrapper, QueryUserWrapper>): QueryUserWrapper
+	}
+
+	public fun <TableUserWrapper : Any, QueryUserWrapper : Any> createUpdate(table: Table<TableUserWrapper, *>, initializer: CreateUpdate<TableUserWrapper, QueryUserWrapper>): Update<QueryUserWrapper>
+
+	public fun interface CreateDelete<TableUserWrapper : Any, QueryUserWrapper : Any> {
+		public fun createDelete(table: Table<TableUserWrapper, *>, creator: DeleteCreator<TableUserWrapper, QueryUserWrapper>): QueryUserWrapper
+	}
+
+	public fun <TableUserWrapper : Any, QueryUserWrapper : Any> createDelete(table: Table<TableUserWrapper, *>, initializer: CreateDelete<TableUserWrapper, QueryUserWrapper>): Delete<QueryUserWrapper>
 
 	public fun <W : Any> substituteModule(rootNs: Namespace, template: ModuleTemplate<W>): Module<W>
 	public fun <W : Any> upgradeModule(oldModule: Module<*>, rootNs: Namespace, template: ModuleTemplate<W>): Module<W>
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/TableCreator.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/TableCreator.kt
index 55a282e..6183c48 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/TableCreator.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/ddl/TableCreator.kt
@@ -25,9 +25,15 @@ public interface TableCreator<TableUserWrapper : Any> {
 	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> nullableColumn(name: String, type: DatabaseType): Column<RuntimeType?, DatabaseType, TableUserWrapper>
 
 	public fun index(name: String, vararg columns: Column<*, *, TableUserWrapper>): Index<TableUserWrapper>
+
+	// todo not-null column uniqueness
 	public fun unique(name: String, distinctNulls: Boolean, vararg columns: Column<*, *, TableUserWrapper>): UniqueConstraint<TableUserWrapper>
 	public fun check(name: String, constraint: Expression<Boolean, ColumnType.BOOLEAN, TableUserWrapper>): CheckConstraint<TableUserWrapper>
 
+	public fun rowIdColumn(): Column<RowId<TableUserWrapper>, ColumnType<RowId<TableUserWrapper>>, TableUserWrapper>
+
+	public fun rowIdUniqueConstraint(): UniqueConstraint<TableUserWrapper>
+
 	public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>> foreignKey(
 		fromColumn: Column<*, ColumnType1, TableUserWrapper>,
 		toTable: Table<TargetTableUserWrapper, *>,
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/Delete.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/Delete.kt
new file mode 100644
index 0000000..0c76949
--- /dev/null
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/Delete.kt
@@ -0,0 +1,5 @@
+package ru.landgrafhomyak.serdha.api.v0.dml
+
+public interface Delete<QueryUserWrapper : Any> {
+	public val userWrapper: QueryUserWrapper
+}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/DeleteCreator.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/DeleteCreator.kt
new file mode 100644
index 0000000..d88b943
--- /dev/null
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/DeleteCreator.kt
@@ -0,0 +1,16 @@
+package ru.landgrafhomyak.serdha.api.v0.dml
+
+import ru.landgrafhomyak.serdha.api.v0.Expression
+import ru.landgrafhomyak.serdha.api.v0.ddl.Column
+import ru.landgrafhomyak.serdha.api.v0.ddl.ColumnType
+import ru.landgrafhomyak.serdha.api.v0.ddl.Table
+
+public interface DeleteCreator<TargetTableUserWrapper : Any, QueryUserWrapper : Any> {
+	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> selectColumn(column: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>): SelectedColumn<RuntimeType, DatabaseType, TargetTableUserWrapper, QueryUserWrapper>
+
+	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> param(name: String, type: DatabaseType): InputParam<RuntimeType, DatabaseType, QueryUserWrapper>
+
+	public fun where(expression: Expression<Boolean, ColumnType.BOOLEAN, QueryUserWrapper>)
+
+	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> returning(e: Expression<RuntimeType, DatabaseType, QueryUserWrapper>): Column<RuntimeType, DatabaseType, QueryUserWrapper>
+}
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/InsertCreator.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/InsertCreator.kt
index d628f7c..98248fb 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/InsertCreator.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/InsertCreator.kt
@@ -6,7 +6,7 @@ import ru.landgrafhomyak.serdha.api.v0.ddl.ColumnType
 import ru.landgrafhomyak.serdha.api.v0.ddl.UniqueConstraint
 
 public interface InsertCreator<TargetTableUserWrapper : Any, QueryUserWrapper : Any> {
-	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> insert(c: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>): InputParam<RuntimeType, DatabaseType, QueryUserWrapper>
+	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> insertTo(c: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>): InputParam<RuntimeType, DatabaseType, QueryUserWrapper>
 
 	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> selectColumn(c: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>): SelectedColumn<RuntimeType, DatabaseType, TargetTableUserWrapper, QueryUserWrapper>
 
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectCreator.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectCreator.kt
index b9fa2ca..48c3562 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectCreator.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectCreator.kt
@@ -8,6 +8,7 @@ import ru.landgrafhomyak.serdha.api.v0.ddl.Table
 public interface SelectCreator<QueryUserWrapper : Any> {
 	public fun <SelectedTableUserWrapper : Any> selectTable(t: Table<SelectedTableUserWrapper, *>): SelectedTable<SelectedTableUserWrapper, QueryUserWrapper>
 	public fun <SelectedQueryUserWrapper : Any> selectQuery(t: Select<SelectedQueryUserWrapper>): SelectedTable<SelectedQueryUserWrapper, QueryUserWrapper>
+
 	public fun where(expression: Expression<Boolean, ColumnType.BOOLEAN, QueryUserWrapper>)
 
 	// default false
@@ -18,4 +19,6 @@ public interface SelectCreator<QueryUserWrapper : Any> {
 	public fun orderBy(vararg columns: Column<*, *, QueryUserWrapper>)
 
 	public fun groupBy(vararg columns: Column<*, *, QueryUserWrapper>)
+
+	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> param(name: String, type: DatabaseType): InputParam<RuntimeType, DatabaseType, QueryUserWrapper>
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectedColumn.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectedColumn.kt
index e016a62..95ee139 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectedColumn.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/SelectedColumn.kt
@@ -3,6 +3,6 @@ package ru.landgrafhomyak.serdha.api.v0.dml
 import ru.landgrafhomyak.serdha.api.v0.Expression
 import ru.landgrafhomyak.serdha.api.v0.ddl.ColumnType
 
-public interface SelectedColumn<RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>, OwnerTypeUserWrapper : Any, QueryUserWrapper : Any> : Expression<RuntimeType, DatabaseType, QueryUserWrapper> {
+public interface SelectedColumn<RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>, OwnerTableUserWrapper : Any, QueryUserWrapper : Any> : Expression<RuntimeType, DatabaseType, QueryUserWrapper> {
 
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/UpdateCreator.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/UpdateCreator.kt
index f092705..5336635 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/UpdateCreator.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/dml/UpdateCreator.kt
@@ -3,9 +3,11 @@ package ru.landgrafhomyak.serdha.api.v0.dml
 import ru.landgrafhomyak.serdha.api.v0.Expression
 import ru.landgrafhomyak.serdha.api.v0.ddl.Column
 import ru.landgrafhomyak.serdha.api.v0.ddl.ColumnType
+import ru.landgrafhomyak.serdha.api.v0.ddl.Table
 
 public interface UpdateCreator<TargetTableUserWrapper : Any, QueryUserWrapper : Any> {
-	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> selectColumn(c: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>): SelectedColumn<RuntimeType, DatabaseType, TargetTableUserWrapper, QueryUserWrapper>
+	public fun <SelectedTableUserWrapper : Any> selectTable(t: Table<SelectedTableUserWrapper, *>): SelectedTable<SelectedTableUserWrapper, QueryUserWrapper>
+	public fun <SelectedQueryUserWrapper : Any> selectQuery(t: Select<SelectedQueryUserWrapper>): SelectedTable<SelectedQueryUserWrapper, QueryUserWrapper>
 
 	public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType & Any>> updateColumn(c: Column<RuntimeType, DatabaseType, TargetTableUserWrapper>, e: Expression<RuntimeType, DatabaseType, QueryUserWrapper>)
 
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/ParametersSetter.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/ParametersSetter.kt
index d947366..c815f76 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/ParametersSetter.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/ParametersSetter.kt
@@ -1,18 +1,19 @@
 package ru.landgrafhomyak.serdha.api.v0.runtime
 
 import ru.landgrafhomyak.serdha.api.v0.ddl.Column
+import ru.landgrafhomyak.serdha.api.v0.dml.InputParam
 
 public interface ParametersSetter<QueryUserWrapper : Any> {
-	public operator fun <RuntimeType> set(c: Column<RuntimeType, *, QueryUserWrapper>, value: RuntimeType)
+	public operator fun <RuntimeType> set(c: InputParam<RuntimeType, *, QueryUserWrapper>, value: RuntimeType)
 
-	public operator fun set(c: Column<Byte, *, QueryUserWrapper>, value: Byte): Unit = this.set<Byte>(c, value)
-	public operator fun set(c: Column<UByte, *, QueryUserWrapper>, value: UByte): Unit = this.set<UByte>(c, value)
-	public operator fun set(c: Column<Short, *, QueryUserWrapper>, value: Short): Unit = this.set<Short>(c, value)
-	public operator fun set(c: Column<UShort, *, QueryUserWrapper>, value: UShort): Unit = this.set<UShort>(c, value)
-	public operator fun set(c: Column<Int, *, QueryUserWrapper>, value: Int): Unit = this.set<Int>(c, value)
-	public operator fun set(c: Column<UInt, *, QueryUserWrapper>, value: UInt): Unit = this.set<UInt>(c, value)
-	public operator fun set(c: Column<Long, *, QueryUserWrapper>, value: Long): Unit = this.set<Long>(c, value)
-	public operator fun set(c: Column<ULong, *, QueryUserWrapper>, value: ULong): Unit = this.set<ULong>(c, value)
-	public operator fun set(c: Column<Char, *, QueryUserWrapper>, value: Char): Unit = this.set<Char>(c, value)
-	public operator fun set(c: Column<Boolean, *, QueryUserWrapper>, value: Boolean): Unit = this.set<Boolean>(c, value)
+	public operator fun set(c: InputParam<Byte, *, QueryUserWrapper>, value: Byte): Unit = this.set<Byte>(c, value)
+	public operator fun set(c: InputParam<UByte, *, QueryUserWrapper>, value: UByte): Unit = this.set<UByte>(c, value)
+	public operator fun set(c: InputParam<Short, *, QueryUserWrapper>, value: Short): Unit = this.set<Short>(c, value)
+	public operator fun set(c: InputParam<UShort, *, QueryUserWrapper>, value: UShort): Unit = this.set<UShort>(c, value)
+	public operator fun set(c: InputParam<Int, *, QueryUserWrapper>, value: Int): Unit = this.set<Int>(c, value)
+	public operator fun set(c: InputParam<UInt, *, QueryUserWrapper>, value: UInt): Unit = this.set<UInt>(c, value)
+	public operator fun set(c: InputParam<Long, *, QueryUserWrapper>, value: Long): Unit = this.set<Long>(c, value)
+	public operator fun set(c: InputParam<ULong, *, QueryUserWrapper>, value: ULong): Unit = this.set<ULong>(c, value)
+	public operator fun set(c: InputParam<Char, *, QueryUserWrapper>, value: Char): Unit = this.set<Char>(c, value)
+	public operator fun set(c: InputParam<Boolean, *, QueryUserWrapper>, value: Boolean): Unit = this.set<Boolean>(c, value)
 }
\ No newline at end of file
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/SynchronizedDatabase.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/SynchronizedDatabase.kt
index 98e71a7..f2da287 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/SynchronizedDatabase.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/SynchronizedDatabase.kt
@@ -2,12 +2,38 @@ package ru.landgrafhomyak.serdha.api.v0.runtime
 
 import ru.landgrafhomyak.serdha.api.v0.LowLevelApi
 import ru.landgrafhomyak.serdha.api.v0.ddl.Module
+import ru.landgrafhomyak.serdha.api.v0.dml.Delete
+import ru.landgrafhomyak.serdha.api.v0.dml.Insert
+import ru.landgrafhomyak.serdha.api.v0.dml.Select
+import ru.landgrafhomyak.serdha.api.v0.dml.Update
 
 public interface SynchronizedDatabase<W : Any> : Module<W> {
 	@Suppress("FunctionName")
 	@LowLevelApi
 	public suspend fun _startTransaction(): Transaction
 
+	@Suppress("FunctionName")
+	@LowLevelApi
+	public suspend fun <QueryUserWrapper : Any> _startAutoTransactedSelect(query: Select<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>>
+
+	@Suppress("FunctionName")
+	@LowLevelApi
+	public suspend fun <QueryUserWrapper : Any> _startAutoTransactedInsert(query: Insert<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>?>
+
+	@Suppress("FunctionName")
+	@LowLevelApi
+	public suspend fun <QueryUserWrapper : Any> _startAutoTransactedUpdate(query: Update<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>?>
+
+	@Suppress("FunctionName")
+	@LowLevelApi
+	public suspend fun <QueryUserWrapper : Any> _startAutoTransactedDelete(query: Delete<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>?>
+
+	public interface AtomicScript<C, A, R> {
+		public suspend fun executeTransaction(transaction: Transaction, context: C, args: A): R
+	}
+
+	public suspend fun <C, A, R> transaction(script: AtomicScript<C, A, R>, context: C, args: A): R
+
 	@Suppress("FunctionName")
 	@LowLevelApi
 	public suspend fun _close()
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/Transaction.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/Transaction.kt
index 07250cf..d76e4f3 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/Transaction.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/Transaction.kt
@@ -1,6 +1,7 @@
 package ru.landgrafhomyak.serdha.api.v0.runtime
 
 import ru.landgrafhomyak.serdha.api.v0.LowLevelApi
+import ru.landgrafhomyak.serdha.api.v0.dml.Delete
 import ru.landgrafhomyak.serdha.api.v0.dml.Insert
 import ru.landgrafhomyak.serdha.api.v0.dml.Select
 import ru.landgrafhomyak.serdha.api.v0.dml.Update
@@ -18,6 +19,10 @@ public interface Transaction {
 	@LowLevelApi
 	public fun <QueryUserWrapper : Any> _update(compiledQuery: Update<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>?>
 
+	@Suppress("FunctionName")
+	@LowLevelApi
+	public fun <QueryUserWrapper : Any> _delete(compiledQuery: Delete<QueryUserWrapper>): _ParametersSetter<QueryUserWrapper, _ResultSet<QueryUserWrapper>?>
+
 	public suspend fun rollback()
 
 	public suspend fun commit()
diff --git a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/transaction_methods.kt b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/transaction_methods.kt
index d62f3be..cd8843e 100644
--- a/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/transaction_methods.kt
+++ b/src/commonMain/kotlin/ru/landgrafhomyak/serdha/api/v0/runtime/transaction_methods.kt
@@ -6,6 +6,7 @@ import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
 import kotlin.jvm.JvmName
 import ru.landgrafhomyak.serdha.api.v0.LowLevelApi
+import ru.landgrafhomyak.serdha.api.v0.dml.Delete
 import ru.landgrafhomyak.serdha.api.v0.dml.Insert
 import ru.landgrafhomyak.serdha.api.v0.dml.Select
 import ru.landgrafhomyak.serdha.api.v0.dml.Update
@@ -166,6 +167,26 @@ internal suspend inline fun <Q : Any, R> _wrapWithLambdasMap(
 }
 
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedSelectSingleOrNull(
+	compiledQuery: Select<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): R? {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.AT_MOST_ONCE)
+	}
+	return _wrapWithLambdasSingleOrNull(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedSelect(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.selectSingleOrNull(
 	compiledQuery: Select<QueryUserWrapper>,
@@ -186,6 +207,7 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.selectSingleOr
 	)
 }
 
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any> Transaction.selectThenIterate(
 	compiledQuery: Select<QueryUserWrapper>,
@@ -206,6 +228,26 @@ public suspend inline fun <QueryUserWrapper : Any> Transaction.selectThenIterate
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedSelectThenIterate(
+	compiledQuery: Select<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> Unit
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	_wrapWithLambdasIterate(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedSelect(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.selectThenMap(
 	compiledQuery: Select<QueryUserWrapper>,
@@ -227,6 +269,27 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.selectThenMap(
 }
 
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedSelectThenMap(
+	compiledQuery: Select<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): List<R> {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	return _wrapWithLambdasMap(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedSelect(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any> Transaction.insert(
 	compiledQuery: Insert<QueryUserWrapper>,
@@ -245,6 +308,24 @@ public suspend inline fun <QueryUserWrapper : Any> Transaction.insert(
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedInsert(
+	compiledQuery: Insert<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+	}
+	_wrapWithLambdas(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedInsert(compiledQuery) },
+		parameters = parameters,
+		hasReturning = false,
+		returning = {},
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.insertReturningSingleOrNull(
 	compiledQuery: Insert<QueryUserWrapper>,
@@ -265,6 +346,26 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.insertReturnin
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedInsertReturningSingleOrNull(
+	compiledQuery: Insert<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): R? {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.AT_MOST_ONCE)
+	}
+	return _wrapWithLambdasSingleOrNull(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedInsert(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any> Transaction.insertReturningIterate(
 	compiledQuery: Insert<QueryUserWrapper>,
@@ -285,6 +386,26 @@ public suspend inline fun <QueryUserWrapper : Any> Transaction.insertReturningIt
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedInsertReturningIterate(
+	compiledQuery: Insert<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> Unit
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	_wrapWithLambdasIterate(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedInsert(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.insertReturningMap(
 	compiledQuery: Insert<QueryUserWrapper>,
@@ -305,6 +426,26 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.insertReturnin
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedInsertReturningMap(
+	compiledQuery: Insert<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): List<R> {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	return _wrapWithLambdasMap(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedInsert(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any> Transaction.update(
 	compiledQuery: Update<QueryUserWrapper>,
@@ -323,6 +464,24 @@ public suspend inline fun <QueryUserWrapper : Any> Transaction.update(
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedUpdate(
+	compiledQuery: Update<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+	}
+	_wrapWithLambdas(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedUpdate(compiledQuery) },
+		parameters = parameters,
+		hasReturning = false,
+		returning = {},
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.updateReturningSingleOrNull(
 	compiledQuery: Update<QueryUserWrapper>,
@@ -343,6 +502,27 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.updateReturnin
 	)
 }
 
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedUpdateReturningSingleOrNull(
+	compiledQuery: Update<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): R? {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.AT_MOST_ONCE)
+	}
+	return _wrapWithLambdasSingleOrNull(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedUpdate(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any> Transaction.updateReturningIterate(
 	compiledQuery: Update<QueryUserWrapper>,
@@ -363,6 +543,26 @@ public suspend inline fun <QueryUserWrapper : Any> Transaction.updateReturningIt
 	)
 }
 
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedUpdateReturningIterate(
+	compiledQuery: Update<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> Unit
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	_wrapWithLambdasIterate(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedUpdate(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
 @OptIn(LowLevelApi::class)
 public suspend inline fun <QueryUserWrapper : Any, R> Transaction.updateReturningMap(
 	compiledQuery: Update<QueryUserWrapper>,
@@ -384,7 +584,184 @@ public suspend inline fun <QueryUserWrapper : Any, R> Transaction.updateReturnin
 }
 
 @OptIn(LowLevelApi::class)
-public suspend fun <R> SynchronizedDatabase<*>.transaction(body: (Transaction) -> R):R {
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedUpdateReturningMap(
+	compiledQuery: Update<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): List<R> {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	return _wrapWithLambdasMap(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedUpdate(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> Transaction.delete(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+	}
+	_wrapWithLambdas(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._delete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = false,
+		returning = {},
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedDelete(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+	}
+	_wrapWithLambdas(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedDelete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = false,
+		returning = {},
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> Transaction.deleteReturningSingleOrNull(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): R? {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.AT_MOST_ONCE)
+	}
+	return _wrapWithLambdasSingleOrNull(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._delete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedDeleteReturningSingleOrNull(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit = {},
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): R? {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.AT_MOST_ONCE)
+	}
+	return _wrapWithLambdasSingleOrNull(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedDelete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> Transaction.deleteReturningIterate(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> Unit
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	_wrapWithLambdasIterate(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._delete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any> SynchronizedDatabase<*>.autoTransactedDeleteReturningIterate(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> Unit
+) {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	_wrapWithLambdasIterate(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedDelete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> Transaction.deleteReturningMap(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): List<R> {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	return _wrapWithLambdasMap(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._delete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend inline fun <QueryUserWrapper : Any, R> SynchronizedDatabase<*>.autoTransactedDeleteReturningMap(
+	compiledQuery: Delete<QueryUserWrapper>,
+	parameters: (ParametersSetter<QueryUserWrapper>) -> Unit,
+	rowsConsumer: (Row<QueryUserWrapper>) -> R
+): List<R> {
+	contract {
+		callsInPlace(parameters, InvocationKind.EXACTLY_ONCE)
+		callsInPlace(rowsConsumer, InvocationKind.UNKNOWN)
+	}
+	return _wrapWithLambdasMap(
+		compiledQuery = compiledQuery,
+		queryGetter = { this._startAutoTransactedDelete(compiledQuery) },
+		parameters = parameters,
+		hasReturning = true,
+		returning = rowsConsumer,
+		""
+	)
+}
+
+@OptIn(LowLevelApi::class)
+public suspend fun <R> SynchronizedDatabase<*>.transaction(body: (Transaction) -> R): R {
 	contract {
 		callsInPlace(body, InvocationKind.EXACTLY_ONCE)
 	}