From 385436642fcf748ac625a4af044d5d0789cb17fd Mon Sep 17 00:00:00 2001
From: Andrew Golovashevich <landgrafhomyak@gmail.com>
Date: Thu, 27 Mar 2025 02:40:36 +0300
Subject: [PATCH] Splitting to files

---
 build.gradle.kts                              |   1 +
 .../PreparedStatementPrepareAndFetch.kt       |   9 --
 .../db/jdbc_kotlin_extensions/autoclose.kt    |  47 ++++++++
 .../db/jdbc_kotlin_extensions/extensions.kt   | 113 ------------------
 .../jdbc_kotlin_extensions/map_resultset.kt   |  22 ++++
 .../db/jdbc_kotlin_extensions/unsigned.kt     |  30 +++++
 6 files changed, 100 insertions(+), 122 deletions(-)
 delete mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/PreparedStatementPrepareAndFetch.kt
 create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/autoclose.kt
 delete mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt
 create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/map_resultset.kt
 create mode 100644 src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/unsigned.kt

diff --git a/build.gradle.kts b/build.gradle.kts
index 5fe6110..afd5397 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -33,6 +33,7 @@ xomrk {
 			jvmMain {
 				dependencies {
 					compileOnly("com.intellij:annotations:9.0.4")
+					implementation("ru.landgrafhomyak.utility:highlevel-try-finally:0.5")
 				}
 			}
 		}
diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/PreparedStatementPrepareAndFetch.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/PreparedStatementPrepareAndFetch.kt
deleted file mode 100644
index 6a4a4bd..0000000
--- a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/PreparedStatementPrepareAndFetch.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package ru.landgrafhomyak.db.jdbc_kotlin_extensions
-
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-
-public interface PreparedStatementPrepareAndFetch<R> {
-    public fun prepare(ps: PreparedStatement)
-    public fun mapOne(rs: ResultSet): R
-}
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/autoclose.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/autoclose.kt
new file mode 100644
index 0000000..17f47b4
--- /dev/null
+++ b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/autoclose.kt
@@ -0,0 +1,47 @@
+@file:JvmName("_AutocloseKt")
+@file:OptIn(ExperimentalContracts::class)
+
+package ru.landgrafhomyak.db.jdbc_kotlin_extensions
+
+import org.intellij.lang.annotations.Language
+import java.sql.Connection
+import java.sql.PreparedStatement
+import java.sql.ResultSet
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
+import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose2
+
+public inline fun <R> Connection.transaction(t: (Connection) -> R): R {
+	contract {
+		callsInPlace(t, InvocationKind.EXACTLY_ONCE)
+	}
+
+	this.executeStatement("BEGIN TRANSACTION")
+	return safeAutoClose2(
+		onError = { this.executeStatement("ROLLBACK TRANSACTION") },
+		onSuccess = { this.executeStatement("COMMIT TRANSACTION") },
+		action = { t(this) }
+	)
+}
+
+public fun Connection.executeStatement(@Language("SQL") sql: String) {
+	this.prepareStatement(sql) { ps -> ps.execute() }
+}
+
+public inline fun <R> Connection.prepareStatement(@Language("SQL") sql: String, action: (PreparedStatement) -> R): R {
+	contract {
+		callsInPlace(action, InvocationKind.EXACTLY_ONCE)
+	}
+	@Suppress("SqlSourceToSinkFlow")
+	val ps = this.prepareStatement(sql)
+	return safeAutoClose1(finally = ps::close) { action(ps) }
+}
+
+public inline fun <R> PreparedStatement.executeQuery(action: (ResultSet) -> R): R {
+	contract {
+		callsInPlace(action, InvocationKind.EXACTLY_ONCE)
+	}
+	return this.executeQuery().use(action)
+}
diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt
deleted file mode 100644
index de2d39a..0000000
--- a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt
+++ /dev/null
@@ -1,113 +0,0 @@
-@file:JvmName("ExtensionsKt")
-@file:Suppress("SqlSourceToSinkFlow")
-@file:OptIn(ExperimentalContracts::class)
-
-package ru.landgrafhomyak.db.jdbc_kotlin_extensions
-
-import org.intellij.lang.annotations.Language
-import java.sql.Connection
-import java.sql.PreparedStatement
-import java.sql.ResultSet
-import kotlin.contracts.ExperimentalContracts
-import kotlin.contracts.InvocationKind
-import kotlin.contracts.contract
-
-public fun <R, C : MutableCollection<R>> Connection.mapQuery(sql: String, action: PreparedStatementPrepareAndFetch<R>, to: C): C {
-	this.prepareStatement(sql).use { ps ->
-		action.prepare(ps)
-		ps.executeQuery().use { rs ->
-			while (rs.next()) {
-				to.add(action.mapOne(rs))
-			}
-		}
-	}
-	return to
-}
-
-public fun <R> Connection.mapQuery(sql: String, action: PreparedStatementPrepareAndFetch<R>): List<R> {
-	val out = ArrayList<R>()
-	this.mapQuery(sql, action, out)
-	return out
-}
-
-public inline fun <R> Connection.transaction(t: (Connection) -> R): R {
-	contract {
-		callsInPlace(t, InvocationKind.EXACTLY_ONCE)
-	}
-
-	this.prepareStatement("BEGIN TRANSACTION").use { ps -> ps.executeUpdate() }
-	val r: R
-	try {
-		r = t(this)
-	} catch (e1: Throwable) {
-		try {
-			this.prepareStatement("ROLLBACK TRANSACTION").use { ps -> ps.executeUpdate() }
-		} catch (e2: Throwable) {
-			e1.addSuppressed(e2)
-		}
-		throw e1
-	}
-	this.prepareStatement("COMMIT TRANSACTION").use { ps -> ps.executeUpdate() }
-	return r
-}
-
-
-public fun Connection.executeStatement(@Language("SQL") sql: String) {
-	this.prepareStatement(sql) { ps -> ps.execute() }
-}
-
-
-public inline fun <R> Connection.prepareStatement(@Language("SQL") sql: String, action: (PreparedStatement) -> R): R {
-	contract {
-		callsInPlace(action, InvocationKind.EXACTLY_ONCE)
-	}
-	this.prepareStatement(sql).use { ps -> return action(ps) }
-}
-
-public inline fun <R, C : MutableCollection<R>> ResultSet.mapTo(to: C, transform: (rs: ResultSet) -> R): C {
-	while (this.next()) {
-		to.add(transform(this))
-	}
-	return to
-}
-
-public inline fun <R> ResultSet.map(transform: (rs: ResultSet) -> R): List<R> =
-	this.mapTo(ArrayList(), transform)
-
-public inline fun <R, C : MutableCollection<R>> ResultSet.mapToThenClose(to: C, transform: (rs: ResultSet) -> R): C =
-	this.use { rs -> rs.mapTo(to, transform) }
-
-public inline fun <R> ResultSet.mapThenClose(transform: (rs: ResultSet) -> R): List<R> =
-	this.use { rs -> rs.map(transform) }
-
-public inline fun <R> PreparedStatement.executeQuery(action: (ResultSet) -> R): R {
-	contract {
-		callsInPlace(action, InvocationKind.EXACTLY_ONCE)
-	}
-	return this.executeQuery().use(action)
-}
-
-
-public fun PreparedStatement.setUByte(parameterIndex: Int, value: UByte): Unit =
-	this.setByte(parameterIndex, value.toByte())
-
-public fun PreparedStatement.setUShort(parameterIndex: Int, value: UShort): Unit =
-	this.setShort(parameterIndex, value.toShort())
-
-public fun PreparedStatement.setUInt(parameterIndex: Int, value: UInt): Unit =
-	this.setInt(parameterIndex, value.toInt())
-
-public fun PreparedStatement.setULong(parameterIndex: Int, value: ULong): Unit =
-	this.setLong(parameterIndex, value.toLong())
-
-public fun ResultSet.getUByte(columnIndex: Int): UByte =
-	this.getByte(columnIndex).toUByte()
-
-public fun ResultSet.getUShort(columnIndex: Int): UShort =
-	this.getShort(columnIndex).toUShort()
-
-public fun ResultSet.getUInt(columnIndex: Int): UInt =
-	this.getInt(columnIndex).toUInt()
-
-public fun ResultSet.getULong(columnIndex: Int): ULong =
-	this.getLong(columnIndex).toULong()
\ No newline at end of file
diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/map_resultset.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/map_resultset.kt
new file mode 100644
index 0000000..eeb4c0a
--- /dev/null
+++ b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/map_resultset.kt
@@ -0,0 +1,22 @@
+@file:JvmName("_MapResultSetKt")
+package ru.landgrafhomyak.db.jdbc_kotlin_extensions
+
+import java.sql.ResultSet
+import ru.landgrafhomyak.utility.highlevel_try_finally.safeAutoClose1
+
+
+public inline fun <R, C : MutableCollection<R>> ResultSet.mapTo(to: C, transform: (rs: ResultSet) -> R): C {
+	while (this.next()) {
+		to.add(transform(this))
+	}
+	return to
+}
+
+public inline fun <R> ResultSet.map(transform: (rs: ResultSet) -> R): List<R> =
+	this.mapTo(ArrayList(), transform)
+
+public inline fun <R, C : MutableCollection<R>> ResultSet.mapToThenClose(to: C, transform: (rs: ResultSet) -> R): C =
+	safeAutoClose1(finally = this::close) { this.mapTo(to, transform) }
+
+public inline fun <R> ResultSet.mapThenClose(transform: (rs: ResultSet) -> R): List<R> =
+	safeAutoClose1(finally = this::close) { this.map(transform) }
diff --git a/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/unsigned.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/unsigned.kt
new file mode 100644
index 0000000..8794cbc
--- /dev/null
+++ b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/unsigned.kt
@@ -0,0 +1,30 @@
+@file:JvmName("_UnsignedKt")
+
+package ru.landgrafhomyak.db.jdbc_kotlin_extensions
+
+import java.sql.PreparedStatement
+import java.sql.ResultSet
+
+public fun PreparedStatement.setUByte(parameterIndex: Int, value: UByte): Unit =
+	this.setByte(parameterIndex, value.toByte())
+
+public fun PreparedStatement.setUShort(parameterIndex: Int, value: UShort): Unit =
+	this.setShort(parameterIndex, value.toShort())
+
+public fun PreparedStatement.setUInt(parameterIndex: Int, value: UInt): Unit =
+	this.setInt(parameterIndex, value.toInt())
+
+public fun PreparedStatement.setULong(parameterIndex: Int, value: ULong): Unit =
+	this.setLong(parameterIndex, value.toLong())
+
+public fun ResultSet.getUByte(columnIndex: Int): UByte =
+	this.getByte(columnIndex).toUByte()
+
+public fun ResultSet.getUShort(columnIndex: Int): UShort =
+	this.getShort(columnIndex).toUShort()
+
+public fun ResultSet.getUInt(columnIndex: Int): UInt =
+	this.getInt(columnIndex).toUInt()
+
+public fun ResultSet.getULong(columnIndex: Int): ULong =
+	this.getLong(columnIndex).toULong()