This commit is contained in:
Andrew Golovashevich 2025-03-24 07:29:07 +03:00
parent 9d2c04a2ad
commit 7874eeea9b
4 changed files with 0 additions and 235 deletions

View File

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

View File

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

View File

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

View File

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