[history/cw-adjutant] Namespaces and table names bound to JDBC SQLite connection
This commit is contained in:
commit
b757b4c589
@ -0,0 +1,102 @@
|
|||||||
|
@file:JvmName("NamespacesSqliteKt")
|
||||||
|
|
||||||
|
package ru.landgrafhomyak.db.raw_sql_skeleton
|
||||||
|
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import java.sql.Connection
|
||||||
|
import java.sql.DriverManager
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
import java.util.concurrent.Executors.newFixedThreadPool
|
||||||
|
import kotlin.coroutines.Continuation
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.coroutines.resumeWithException
|
||||||
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
|
|
||||||
|
public class SqliteConnection private constructor(
|
||||||
|
internal val jdbcConnection: Connection,
|
||||||
|
) {
|
||||||
|
private val executor = newFixedThreadPool(1)
|
||||||
|
|
||||||
|
private val mutex = Mutex()
|
||||||
|
|
||||||
|
private inner class Task<R>(
|
||||||
|
private val continuation: Continuation<R>,
|
||||||
|
private val task: (connection: Connection) -> R,
|
||||||
|
) : Callable<Unit> {
|
||||||
|
override fun call() {
|
||||||
|
try {
|
||||||
|
this.continuation.resume(this.task(this@SqliteConnection.jdbcConnection))
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
this.continuation.resumeWithException(RuntimeException("runner interrupted"))
|
||||||
|
throw e
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
this.continuation.resumeWithException(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun <R> transaction(body: (connection: Connection) -> R): R = this.raw { connection ->
|
||||||
|
return@raw connection.transaction(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
public suspend fun <R> raw(action: (Connection) -> R): R = this.mutex.withLock {
|
||||||
|
return@withLock suspendCoroutine { continuation ->
|
||||||
|
this.executor.submit(this.Task(continuation, action))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public val rootNamespace: SqliteNamespace = SqliteNamespace(this, emptyArray())
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
@JvmStatic
|
||||||
|
public suspend fun wrap7prepare(rawConnection: Connection): SqliteConnection {
|
||||||
|
val w = SqliteConnection(rawConnection)
|
||||||
|
w.raw { connection ->
|
||||||
|
connection.autoCommit = false
|
||||||
|
connection.prepareStatement("ROLLBACK TRANSACTION") { ps -> ps.execute() }
|
||||||
|
connection.prepareStatement("PRAGMA foreign_keys=TRUE") { ps -> ps.execute() }
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
public suspend fun connect(url: String): SqliteConnection = this.wrap7prepare(DriverManager.getConnection(url))
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
public fun connectBlocking(url: String): SqliteConnection = runBlocking { this@Companion.connect(url) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SqliteNamespace(
|
||||||
|
private val owner: SqliteConnection,
|
||||||
|
private val path: Array<String>,
|
||||||
|
) {
|
||||||
|
private val usedNames = HashSet<String>()
|
||||||
|
|
||||||
|
public fun subNamespace(name: String): SqliteNamespace {
|
||||||
|
if (name in this.usedNames)
|
||||||
|
throw IllegalArgumentException("Name is already used: $name")
|
||||||
|
this.usedNames.add(name)
|
||||||
|
return SqliteNamespace(this.owner, this.path + name)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun table(name: String): SqliteTableName {
|
||||||
|
if (name in this.usedNames)
|
||||||
|
throw IllegalArgumentException("Name is already used: $name")
|
||||||
|
this.usedNames.add(name)
|
||||||
|
|
||||||
|
return SqliteTableName(this.formatTableName(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun formatTableName(name: String) = this.path.joinToString(prefix = "\"::", separator = "::", postfix = "::${name}\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
public value class SqliteTableName(private val value: String) {
|
||||||
|
override fun toString(): String = this.value
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user