SQLDelight multiplatform runtime library providing Kotlin APIs for type-safe database operations with compile-time SQL verification
npx @tessl/cli install tessl/maven-app-cash-sqldelight--runtime-iossimulatorarm64@2.1.0SQLDelight Runtime is a Kotlin Multiplatform library that provides the foundational runtime components for SQLDelight-generated database code. It offers type-safe database operations, transaction management, and cross-platform database abstraction with first-class support for both synchronous and asynchronous execution patterns.
implementation("app.cash.sqldelight:runtime:2.1.0")import app.cash.sqldelight.Query
import app.cash.sqldelight.Transacter
import app.cash.sqldelight.ColumnAdapter
import app.cash.sqldelight.db.SqlDriver
import app.cash.sqldelight.db.SqlCursor
import app.cash.sqldelight.db.QueryResultimport app.cash.sqldelight.Query
import app.cash.sqldelight.Transacter
import app.cash.sqldelight.db.SqlDriver
// Executing a query (typically generated by SQLDelight)
val query: Query<User> = // ... generated query
val users: List<User> = query.executeAsList()
val singleUser: User? = query.executeAsOneOrNull()
// Transaction management
class MyDatabase(driver: SqlDriver) : TransacterImpl(driver) {
fun transferMoney(fromId: Long, toId: Long, amount: Double) {
transaction {
// Update account balances atomically
updateBalance(fromId, -amount)
updateBalance(toId, amount)
}
}
}
// Column adapters for custom types
val dateAdapter = object : ColumnAdapter<LocalDate, String> {
override fun decode(databaseValue: String): LocalDate = LocalDate.parse(databaseValue)
override fun encode(value: LocalDate): String = value.toString()
}SQLDelight Runtime is built around several key components:
Core query execution functionality providing type-safe database operations with result mapping and change notification.
abstract class Query<out RowType : Any>(
mapper: (SqlCursor) -> RowType
) : ExecutableQuery<RowType>(mapper) {
abstract fun addListener(listener: Listener)
abstract fun removeListener(listener: Listener)
fun interface Listener {
fun queryResultsChanged()
}
}
abstract class ExecutableQuery<out RowType : Any>(
val mapper: (SqlCursor) -> RowType
) {
abstract fun <R> execute(mapper: (SqlCursor) -> QueryResult<R>): QueryResult<R>
fun executeAsList(): List<RowType>
fun executeAsOne(): RowType
fun executeAsOneOrNull(): RowType?
}Comprehensive transaction management with support for nested transactions, rollback semantics, and lifecycle callbacks.
interface Transacter : TransacterBase {
fun <R> transactionWithResult(
noEnclosing: Boolean = false,
bodyWithReturn: TransactionWithReturn<R>.() -> R
): R
fun transaction(
noEnclosing: Boolean = false,
body: TransactionWithoutReturn.() -> Unit
)
}
interface SuspendingTransacter : TransacterBase {
suspend fun <R> transactionWithResult(
noEnclosing: Boolean = false,
bodyWithReturn: suspend SuspendingTransactionWithReturn<R>.() -> R
): R
suspend fun transaction(
noEnclosing: Boolean = false,
body: suspend SuspendingTransactionWithoutReturn.() -> Unit
)
}Low-level database driver abstraction providing platform-agnostic SQL execution and connection management.
interface SqlDriver : Closeable {
fun <R> executeQuery(
identifier: Int?,
sql: String,
mapper: (SqlCursor) -> QueryResult<R>,
parameters: Int,
binders: (SqlPreparedStatement.() -> Unit)? = null
): QueryResult<R>
fun execute(
identifier: Int?,
sql: String,
parameters: Int,
binders: (SqlPreparedStatement.() -> Unit)? = null
): QueryResult<Long>
fun newTransaction(): QueryResult<Transacter.Transaction>
fun currentTransaction(): Transacter.Transaction?
}Type marshaling system for converting between Kotlin types and database-supported primitives with built-in enum support.
interface ColumnAdapter<T : Any, S> {
fun decode(databaseValue: S): T
fun encode(value: T): S
}
class EnumColumnAdapter<T : Enum<T>> internal constructor(
private val enumValues: Array<out T>
) : ColumnAdapter<T, String>
inline fun <reified T : Enum<T>> EnumColumnAdapter(): EnumColumnAdapter<T>Database schema creation, versioning, and migration support with callback-based upgrade logic.
interface SqlSchema<T : QueryResult<Unit>> {
val version: Long
fun create(driver: SqlDriver): T
fun migrate(driver: SqlDriver, oldVersion: Long, newVersion: Long, vararg callbacks: AfterVersion): T
}
class AfterVersion(
val afterVersion: Long,
val block: (SqlDriver) -> Unit
)Comprehensive logging support for debugging database operations with query and transaction visibility.
class LogSqliteDriver(
private val sqlDriver: SqlDriver,
private val logger: (String) -> Unit
) : SqlDriversealed interface QueryResult<T> {
val value: T
suspend fun await(): T
@JvmInline
value class Value<T>(override val value: T) : QueryResult<T>
@JvmInline
value class AsyncValue<T>(private val getter: suspend () -> T) : QueryResult<T>
}
interface SqlCursor {
fun next(): QueryResult<Boolean>
fun getString(index: Int): String?
fun getLong(index: Int): Long?
fun getBytes(index: Int): ByteArray?
fun getDouble(index: Int): Double?
fun getBoolean(index: Int): Boolean?
}
interface SqlPreparedStatement {
fun bindBytes(index: Int, bytes: ByteArray?)
fun bindLong(index: Int, long: Long?)
fun bindDouble(index: Int, double: Double?)
fun bindString(index: Int, string: String?)
fun bindBoolean(index: Int, boolean: Boolean?)
}
expect interface Closeable {
fun close()
}
expect inline fun <T : Closeable?, R> T.use(body: (T) -> R): R
class OptimisticLockException(message: String?, cause: Throwable? = null) : IllegalStateException(message, cause)