Compare commits

...

3 Commits
v0.1 ... master

9 changed files with 174 additions and 122 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
/.idea/
gradle/
.gradle/
build/
*.class
*.jar
/out/
/gradlew*
.kotlin/

64
build.gradle.kts Normal file
View File

@ -0,0 +1,64 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.*
import ru.landgrafhomyak.kotlin.kmp_gradle_build_helper.plugin.xomrk
buildscript {
repositories {
mavenCentral()
maven("https://maven.landgrafhomyak.ru/")
}
dependencies {
classpath("ru.landgrafhomyak.kotlin:kotlin-mpp-gradle-build:v0.3k2.1.10")
}
}
group = "ru.landgrafhomyak.db"
version = "0.2"
repositories {
mavenCentral()
maven("https://maven.landgrafhomyak.ru/")
}
xomrk {
kotlin {
setCompatibilityWithKotlin(KotlinVersion.KOTLIN_2_0)
optInContracts()
explicitApi()
jvmToolchain(8)
jvm {
compilations.configureEach {
compileJavaTaskProvider?.configure {
targetCompatibility = "1.8"
}
compileTaskProvider.configure {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
}
sourceSets {
val kotlinStdlibDependency = "org.jetbrains.kotlin:kotlin-stdlib:${this@kotlin.coreLibrariesVersion}"
jvmMain {
dependencies {
compileOnly(kotlinStdlibDependency)
compileOnly("com.intellij:annotations:9.0.4")
implementation("ru.landgrafhomyak.utility:highlevel-try-finally:0.5")
}
}
}
}
publishing {
repositories {
defineXomrkGiteaMavenRepo()
}
forceSetAllMavenArtifactsId(project.name)
}
}

1
gradle.properties Normal file
View File

@ -0,0 +1 @@
kotlin.stdlib.default.dependency=false

1
settings.gradle.kts Normal file
View File

@ -0,0 +1 @@
rootProject.name = "jdbc-kotlin-extensions"

View File

@ -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
}

View File

@ -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)
}

View File

@ -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()

View File

@ -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) }

View File

@ -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()