From b75b9ef415d61da6be68202880737ab5c459b760 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Mon, 19 Aug 2024 05:23:00 +0300 Subject: [PATCH] [history] Scopes for transaction and prepared statement --- .../PreparedStatementPrepareAndFetch.kt | 9 +++ .../db/jdbc_kotlin_extensions/extensions.kt | 56 +++++++++++++++++++ 2 files changed, 65 insertions(+) create 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/extensions.kt 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 new file mode 100644 index 0000000..6a4a4bd --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/PreparedStatementPrepareAndFetch.kt @@ -0,0 +1,9 @@ +package ru.landgrafhomyak.db.jdbc_kotlin_extensions + +import java.sql.PreparedStatement +import java.sql.ResultSet + +public interface PreparedStatementPrepareAndFetch { + 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/extensions.kt b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt new file mode 100644 index 0000000..ba9ef0b --- /dev/null +++ b/src/jvmMain/kotlin/ru/landgrafhomyak/db/jdbc_kotlin_extensions/extensions.kt @@ -0,0 +1,56 @@ +@file:JvmName("ExtensionsKt") +@file:Suppress("SqlSourceToSinkFlow") +@file:OptIn(ExperimentalContracts::class) + +package ru.landgrafhomyak.db.jdbc_kotlin_extensions + +import java.sql.Connection +import java.sql.PreparedStatement +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +public fun Connection.mapQuery(sql: String, action: PreparedStatementPrepareAndFetch, to: MutableList) { + this.prepareStatement(sql).use { ps -> + action.prepare(ps) + ps.executeQuery().use { rs -> + while (rs.next()) { + to.add(action.mapOne(rs)) + } + } + } +} + +public fun Connection.mapQuery(sql: String, action: PreparedStatementPrepareAndFetch): List { + val out = ArrayList() + this.mapQuery(sql, action, out) + return out +} + +public inline fun Connection.transaction(t: (Connection) -> R): R { + contract { + callsInPlace(t) + } + + 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 inline fun Connection.prepareStatement(sql: String, action: (PreparedStatement) -> R): R { + contract { + callsInPlace(action) + } + this.prepareStatement(sql).use { ps -> return action(ps) } +} \ No newline at end of file