0
# SQLDelight Runtime
1
2
SQLDelight Runtime is the multiplatform runtime library for SQLDelight, providing typesafe Kotlin APIs from SQL statements. It serves as the foundational layer that enables compile-time schema verification, reactive query results, and thread-safe database operations across JVM, Android, Native, and JavaScript platforms.
3
4
## Package Information
5
6
- **Package Name**: app.cash.sqldelight:runtime
7
- **Package Type**: Maven/Gradle
8
- **Language**: Kotlin (Multiplatform)
9
- **Installation**: `implementation "app.cash.sqldelight:runtime:2.1.0"`
10
11
## Core Imports
12
13
```kotlin
14
import app.cash.sqldelight.Query
15
import app.cash.sqldelight.Transacter
16
import app.cash.sqldelight.SuspendingTransacter
17
import app.cash.sqldelight.ColumnAdapter
18
import app.cash.sqldelight.EnumColumnAdapter
19
import app.cash.sqldelight.db.SqlDriver
20
import app.cash.sqldelight.db.SqlCursor
21
import app.cash.sqldelight.db.QueryResult
22
import app.cash.sqldelight.db.SqlSchema
23
import app.cash.sqldelight.db.AfterVersion
24
import app.cash.sqldelight.logs.LogSqliteDriver
25
import app.cash.sqldelight.logs.StatementParameterInterceptor
26
```
27
28
## Basic Usage
29
30
```kotlin
31
import app.cash.sqldelight.Query
32
import app.cash.sqldelight.Transacter
33
import app.cash.sqldelight.db.SqlDriver
34
35
// Execute a query and get results
36
val users: List<User> = userQueries.selectAll().executeAsList()
37
38
// Execute a single result query
39
val user: User? = userQueries.selectById(123).executeAsOneOrNull()
40
41
// Listen to query result changes
42
userQueries.selectAll().addListener(object : Query.Listener {
43
override fun queryResultsChanged() {
44
// Handle query result updates
45
updateUI()
46
}
47
})
48
49
// Execute operations in a transaction
50
database.transaction {
51
userQueries.insertUser("Alice", 25)
52
userQueries.insertUser("Bob", 30)
53
// Both inserts succeed or both are rolled back
54
}
55
```
56
57
## Architecture
58
59
SQLDelight Runtime is built around several key components:
60
61
- **Query System**: Type-safe query execution with reactive result updates via the observer pattern
62
- **Transaction Management**: ACID transaction support with nested transaction capabilities and automatic resource cleanup
63
- **Driver Abstraction**: Platform-agnostic database driver interface supporting both synchronous and asynchronous operations
64
- **Type Adaptation**: Bidirectional type conversion system for mapping between Kotlin types and database column types
65
- **Multiplatform Design**: Common API surface with platform-specific implementations using expect/actual declarations
66
- **Resource Management**: Automatic cleanup and proper lifecycle management through Closeable pattern
67
68
## Capabilities
69
70
### Query Execution and Management
71
72
Core query functionality for executing SQL statements and managing result sets. Provides type-safe query execution with reactive updates and lifecycle management.
73
74
```kotlin { .api }
75
abstract class Query<out RowType : Any>(
76
mapper: (SqlCursor) -> RowType
77
) : ExecutableQuery<RowType>(mapper) {
78
abstract fun addListener(listener: Listener)
79
abstract fun removeListener(listener: Listener)
80
81
fun interface Listener {
82
fun queryResultsChanged()
83
}
84
}
85
86
abstract class ExecutableQuery<out RowType : Any>(
87
val mapper: (SqlCursor) -> RowType
88
) {
89
abstract fun <R> execute(mapper: (SqlCursor) -> QueryResult<R>): QueryResult<R>
90
fun executeAsList(): List<RowType>
91
fun executeAsOne(): RowType
92
fun executeAsOneOrNull(): RowType?
93
}
94
95
// Factory functions for creating queries
96
fun <RowType : Any> Query(
97
identifier: Int,
98
queryKeys: Array<out String>,
99
driver: SqlDriver,
100
query: String,
101
mapper: (SqlCursor) -> RowType
102
): Query<RowType>
103
```
104
105
[Query System](./query-system.md)
106
107
### Transaction Management
108
109
Comprehensive transaction support with ACID guarantees, nested transactions, and automatic resource management. Supports both synchronous and coroutine-based asynchronous operations.
110
111
```kotlin { .api }
112
interface Transacter : TransacterBase {
113
fun <R> transactionWithResult(
114
noEnclosing: Boolean = false,
115
bodyWithReturn: TransactionWithReturn<R>.() -> R
116
): R
117
118
fun transaction(
119
noEnclosing: Boolean = false,
120
body: TransactionWithoutReturn.() -> Unit
121
)
122
}
123
124
interface SuspendingTransacter : TransacterBase {
125
suspend fun <R> transactionWithResult(
126
noEnclosing: Boolean = false,
127
bodyWithReturn: suspend SuspendingTransactionWithReturn<R>.() -> R
128
): R
129
130
suspend fun transaction(
131
noEnclosing: Boolean = false,
132
body: suspend SuspendingTransactionWithoutReturn.() -> Unit
133
)
134
}
135
136
abstract class Transacter.Transaction : TransactionCallbacks {
137
protected abstract val enclosingTransaction: Transaction?
138
fun afterCommit(function: () -> Unit)
139
fun afterRollback(function: () -> Unit)
140
protected abstract fun endTransaction(successful: Boolean): QueryResult<Unit>
141
}
142
```
143
144
[Transaction Management](./transaction-management.md)
145
146
### Database Driver Interface
147
148
Platform-agnostic database driver abstraction that provides SQL execution, connection management, and query result handling. Supports both synchronous and asynchronous operation modes.
149
150
```kotlin { .api }
151
interface SqlDriver : Closeable {
152
fun <R> executeQuery(
153
identifier: Int?,
154
sql: String,
155
mapper: (SqlCursor) -> QueryResult<R>,
156
parameters: Int,
157
binders: (SqlPreparedStatement.() -> Unit)? = null
158
): QueryResult<R>
159
160
fun execute(
161
identifier: Int?,
162
sql: String,
163
parameters: Int,
164
binders: (SqlPreparedStatement.() -> Unit)? = null
165
): QueryResult<Long>
166
167
fun newTransaction(): QueryResult<Transacter.Transaction>
168
fun currentTransaction(): Transacter.Transaction?
169
fun addListener(vararg queryKeys: String, listener: Query.Listener)
170
fun removeListener(vararg queryKeys: String, listener: Query.Listener)
171
fun notifyListeners(vararg queryKeys: String)
172
}
173
174
interface SqlCursor {
175
fun next(): QueryResult<Boolean>
176
fun getString(index: Int): String?
177
fun getLong(index: Int): Long?
178
fun getBytes(index: Int): ByteArray?
179
fun getDouble(index: Int): Double?
180
fun getBoolean(index: Int): Boolean?
181
}
182
183
sealed interface QueryResult<T> {
184
val value: T
185
suspend fun await(): T
186
187
value class Value<T>(override val value: T) : QueryResult<T>
188
value class AsyncValue<T>(private val getter: suspend () -> T) : QueryResult<T>
189
}
190
```
191
192
[Database Driver Interface](./database-driver.md)
193
194
### Column Type Adapters
195
196
Type conversion system for mapping between Kotlin types and database column types. Enables custom type serialization and provides built-in adapters for common use cases.
197
198
```kotlin { .api }
199
interface ColumnAdapter<T : Any, S> {
200
fun decode(databaseValue: S): T
201
fun encode(value: T): S
202
}
203
204
class EnumColumnAdapter<T : Enum<T>>(
205
private val enumValues: Array<out T>
206
) : ColumnAdapter<T, String> {
207
override fun decode(databaseValue: String): T
208
override fun encode(value: T): String
209
}
210
211
// Factory function for enum adapters
212
inline fun <reified T : Enum<T>> EnumColumnAdapter(): EnumColumnAdapter<T>
213
```
214
215
[Column Type Adapters](./column-adapters.md)
216
217
### Logging and Debugging Utilities
218
219
Comprehensive logging and debugging tools for monitoring database operations, troubleshooting issues, and performance analysis.
220
221
```kotlin { .api }
222
class LogSqliteDriver(
223
private val sqlDriver: SqlDriver,
224
private val logger: (String) -> Unit
225
) : SqlDriver {
226
// Logs all SQL operations including queries, executions, transactions
227
override fun <R> executeQuery(
228
identifier: Int?,
229
sql: String,
230
mapper: (SqlCursor) -> QueryResult<R>,
231
parameters: Int,
232
binders: (SqlPreparedStatement.() -> Unit)?
233
): QueryResult<R>
234
235
override fun execute(
236
identifier: Int?,
237
sql: String,
238
parameters: Int,
239
binders: (SqlPreparedStatement.() -> Unit)?
240
): QueryResult<Long>
241
}
242
243
class StatementParameterInterceptor : SqlPreparedStatement {
244
fun getAndClearParameters(): List<Any?>
245
// Intercepts and stores parameter values for debugging
246
}
247
```
248
249
[Logging and Utilities](./logging-utilities.md)
250
251
### Schema Management
252
253
Database schema creation, migration, and version management system. Provides APIs for initializing databases and handling schema changes across application versions.
254
255
```kotlin { .api }
256
interface SqlSchema<T : QueryResult<Unit>> {
257
val version: Long
258
fun create(driver: SqlDriver): T
259
fun migrate(
260
driver: SqlDriver,
261
oldVersion: Long,
262
newVersion: Long,
263
vararg callbacks: AfterVersion
264
): T
265
}
266
267
class AfterVersion(
268
val afterVersion: Long,
269
val block: (SqlDriver) -> Unit
270
)
271
```
272
273
[Schema Management](./schema-management.md)
274
275
## Types
276
277
```kotlin { .api }
278
// Core interfaces
279
sealed interface TransacterBase {
280
// Base interface for all transaction-capable components
281
// Implemented by Transacter and SuspendingTransacter
282
}
283
interface TransactionCallbacks {
284
fun afterCommit(function: () -> Unit)
285
fun afterRollback(function: () -> Unit)
286
}
287
288
// Transaction context interfaces
289
interface TransactionWithReturn<R> : TransactionCallbacks {
290
fun rollback(returnValue: R): Nothing
291
fun <R> transaction(body: TransactionWithReturn<R>.() -> R): R
292
}
293
294
interface TransactionWithoutReturn : TransactionCallbacks {
295
fun rollback(): Nothing
296
fun transaction(body: TransactionWithoutReturn.() -> Unit)
297
}
298
299
interface SuspendingTransactionWithReturn<R> : TransactionCallbacks {
300
fun rollback(returnValue: R): Nothing
301
suspend fun <R> transaction(body: suspend SuspendingTransactionWithReturn<R>.() -> R): R
302
}
303
304
interface SuspendingTransactionWithoutReturn : TransactionCallbacks {
305
fun rollback(): Nothing
306
suspend fun transactionWithResult(body: suspend SuspendingTransactionWithoutReturn.() -> Unit)
307
}
308
309
// Prepared statement interface
310
interface SqlPreparedStatement {
311
fun bindBytes(index: Int, bytes: ByteArray?)
312
fun bindLong(index: Int, long: Long?)
313
fun bindDouble(index: Int, double: Double?)
314
fun bindString(index: Int, string: String?)
315
fun bindBoolean(index: Int, boolean: Boolean?)
316
}
317
318
// Platform abstraction
319
expect interface Closeable {
320
fun close()
321
}
322
323
expect inline fun <T : Closeable?, R> T.use(body: (T) -> R): R
324
325
// Exception types
326
class OptimisticLockException(
327
message: String?,
328
cause: Throwable? = null
329
) : IllegalStateException(message, cause)
330
331
// Internal APIs
332
internal expect fun currentThreadId(): Long
333
```