Cleanup
This commit is contained in:
parent
9d2c04a2ad
commit
7874eeea9b
@ -1,76 +0,0 @@
|
|||||||
package ru.landgrafhomyak.db.serdha0.api.module
|
|
||||||
|
|
||||||
import ru.landgrafhomyak.db.raw_sql_skeleton.Table
|
|
||||||
import ru.landgrafhomyak.db.serdha0.api.queries._Query
|
|
||||||
import ru.landgrafhomyak.db.raw_sql_skeleton.TableConstructor
|
|
||||||
import ru.landgrafhomyak.serdha0.api.module.Namespace
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope methods for creating new [module template][ModuleTemplate].
|
|
||||||
*
|
|
||||||
* @see ModuleTemplate.CreateModuleTemplatesScope.createTemplate
|
|
||||||
* @see ModuleTemplate.ModuleCreator.createSchema
|
|
||||||
*/
|
|
||||||
public interface CreateModuleScope {
|
|
||||||
public val rootNs: Namespace
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates table in [specified namespace][namespace] with [specified name][name] and stores it in the database.
|
|
||||||
* If table was created by previous synchronizations, asserts that table at the specified path in the database is same as table provided by [initializer].
|
|
||||||
*
|
|
||||||
* On [module upgrading][ModuleTemplate.CreateModuleTemplatesScope.upgradeTemplate] this table must be [kept][UpgradeModuleScope.upgradeTable] (or [renamed][UpgradeModuleScope.renameTable]) or [deleted][UpgradeModuleScope.deleteTable].
|
|
||||||
*
|
|
||||||
* @param tUE User's type for containing table-related descriptors.
|
|
||||||
* @param namespace Way to group tables if there is a lot.
|
|
||||||
* @param name Name of table for debugging.
|
|
||||||
* @param initializer Table-related descriptors initializer.
|
|
||||||
* @return Table descriptor.
|
|
||||||
*/
|
|
||||||
public fun <tUE : Any> createTable(namespace: Namespace = this.rootNs, name: String, initializer: TableConstructor<tUE>): Table<tUE, Nothing>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a temporary table that exits only until connection to the database not [closed][SynchronizedDatabase._close].
|
|
||||||
*
|
|
||||||
* On [module upgrading][ModuleTemplate.CreateModuleTemplatesScope.upgradeTemplate] must be recreated if needed.
|
|
||||||
*
|
|
||||||
* @param tUE User's type for containing table-related descriptors.
|
|
||||||
* @param namespace Way to group tables if there is a lot.
|
|
||||||
* @param name Name of table for debugging.
|
|
||||||
* @param initializer Table-related descriptors initializer.
|
|
||||||
* @return Table descriptor.
|
|
||||||
*/
|
|
||||||
public fun <tUE : Any> createSessionScopeTemporaryTable(namespace: Namespace = this.rootNs, name: String, initializer: TableConstructor<tUE>): Table<tUE, Nothing>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a temporary table that exits only inside [transaction][Transaction] and auto-deleted (or cleared, depends on driver implementation) when it [finished][Transaction._assertTransactionFinishedAndReleaseResources].
|
|
||||||
*
|
|
||||||
* On [module upgrading][ModuleTemplate.CreateModuleTemplatesScope.upgradeTemplate] must be recreated if needed.
|
|
||||||
*
|
|
||||||
* @param tUE User's type for containing table-related descriptors.
|
|
||||||
* @param namespace Way to group tables if there is a lot.
|
|
||||||
* @param name Name of table for debugging.
|
|
||||||
* @param initializer Table-related descriptors initializer.
|
|
||||||
* @return Table descriptor.
|
|
||||||
*/
|
|
||||||
public fun <tUE : Any> createTransactionScopeTemporaryTable(namespace: Namespace = this.rootNs, name: String, initializer: TableConstructor<tUE>): Table<tUE, Nothing>
|
|
||||||
|
|
||||||
public val queries: _Query.Constructor.Scope
|
|
||||||
|
|
||||||
public val temporarySubqueries: _Query.Constructor.Scope
|
|
||||||
|
|
||||||
public val moduleConfiguringTemporaryQueries: _Query.Constructor.Scope
|
|
||||||
|
|
||||||
public fun <qUE : Any> createQuery(creator: _Query.Constructor<qUE>): qUE
|
|
||||||
|
|
||||||
public fun <qUE : Any> createModuleConfiguringTemporaryQuery(creator: _Query.Constructor<qUE>): qUE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces [specified namespace][rootNs] with schema provided by [template].
|
|
||||||
* [This namespace][rootNs] will be root namespace for module and shouldn't contain any other definitions.
|
|
||||||
*
|
|
||||||
* @param rootNs Namespace where the new module will be located.
|
|
||||||
* @param template Schema template.
|
|
||||||
* @return Module descriptor.
|
|
||||||
*/
|
|
||||||
public fun <mUE : Any> substituteModule(rootNs: Namespace, template: ModuleTemplate<mUE>): Module<mUE>
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package ru.landgrafhomyak.db.serdha0.api.module
|
|
||||||
|
|
||||||
import kotlin.jvm.JvmName
|
|
||||||
import ru.landgrafhomyak.db.serdha0.api.runtime.SynchronizedDatabase
|
|
||||||
|
|
||||||
public interface Module<mUE : Any> {
|
|
||||||
|
|
||||||
public val uExt: mUE
|
|
||||||
|
|
||||||
public val versionKey: String
|
|
||||||
|
|
||||||
public val ownerDatabase: SynchronizedDatabase<*>
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package ru.landgrafhomyak.db.serdha0.api.module
|
|
||||||
|
|
||||||
import ru.landgrafhomyak.db.serdha0.api.runtime.Transaction
|
|
||||||
|
|
||||||
public interface ModuleTemplate<@Suppress("unused") mUE : Any> {
|
|
||||||
public interface VersionsInitializer<UE : Any> {
|
|
||||||
public fun createModuleTemplates(context: Scope): UE
|
|
||||||
|
|
||||||
public interface Scope {
|
|
||||||
public fun <nmUE : Any> createTemplate(
|
|
||||||
constructor: ModuleConstructor<nmUE>,
|
|
||||||
): ModuleTemplate<nmUE>
|
|
||||||
|
|
||||||
public fun <omUE : Any, nmUE : Any> upgradeTemplate(
|
|
||||||
oldModule: ModuleTemplate<omUE>,
|
|
||||||
upgrade: ModuleUpgrade<omUE, nmUE>,
|
|
||||||
): ModuleTemplate<nmUE>
|
|
||||||
|
|
||||||
public fun <omUE : Any, nmUE : Any> upgradeTemplateAndMerge(
|
|
||||||
oldModule: ModuleTemplate<omUE>,
|
|
||||||
upgrade: ModuleUpgrade<omUE, nmUE>,
|
|
||||||
mergeTo: ModuleTemplate<nmUE>
|
|
||||||
): ModuleTemplate<nmUE>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ModuleConstructor<mUE : Any> {
|
|
||||||
public val versionKey: String
|
|
||||||
|
|
||||||
public fun createSchema(context: CreateModuleScope): mUE
|
|
||||||
|
|
||||||
public suspend fun initData(ext: mUE, transaction: Transaction) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ModuleUpgrade<omUE : Any, nmUE : Any> {
|
|
||||||
public val versionKey: String
|
|
||||||
|
|
||||||
public fun upgradeSchema(context: UpgradeModuleScope<omUE>): nmUE
|
|
||||||
|
|
||||||
public suspend fun upgradeData(ext: nmUE, transaction: Transaction) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
public val versionKey: String
|
|
||||||
}
|
|
@ -1,102 +0,0 @@
|
|||||||
@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}")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class SqliteTableName(private val name: String) {
|
|
||||||
public val asSqlReference: String = "\"${this.name}\""
|
|
||||||
public val asSqlString: String = "\'${this.name}\'"
|
|
||||||
override fun toString(): String = this.asSqlReference
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user