commonMain.app.cash.sqldelight.Query.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of runtime Show documentation
Show all versions of runtime Show documentation
Multiplatform runtime library to support generated code
The newest version!
/*
* Copyright (C) 2018 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package app.cash.sqldelight
import app.cash.sqldelight.db.QueryResult
import app.cash.sqldelight.db.SqlCursor
import app.cash.sqldelight.db.SqlDriver
/**
* A listenable, typed query generated by SQLDelight.
*
* @param RowType the type that this query can map its result set to.
*/
@Suppress("FunctionName") // Emulating a constructor.
fun Query(
identifier: Int,
queryKeys: Array,
driver: SqlDriver,
query: String,
mapper: (SqlCursor) -> RowType,
): Query {
return Query(identifier, queryKeys, driver, "unknown", "unknown", query, mapper)
}
/**
* A listenable, typed query generated by SQLDelight.
*
* @param RowType the type that this query can map its result set to.
*/
@Suppress("FunctionName") // Emulating a constructor.
fun Query(
identifier: Int,
queryKeys: Array,
driver: SqlDriver,
fileName: String,
label: String,
query: String,
mapper: (SqlCursor) -> RowType,
): Query {
return SimpleQuery(identifier, queryKeys, driver, fileName, label, query, mapper)
}
/**
* A listenable, typed query generated by SQLDelight.
*
* @param RowType the type that this query can map its result set to.
*/
@Suppress("FunctionName") // Emulating a constructor.
fun Query(
identifier: Int,
driver: SqlDriver,
query: String,
mapper: (SqlCursor) -> RowType,
): ExecutableQuery {
return Query(identifier, driver, "unknown", "unknown", query, mapper)
}
/**
* A listenable, typed query generated by SQLDelight.
*
* @param RowType the type that this query can map its result set to.
*/
@Suppress("FunctionName") // Emulating a constructor.
fun Query(
identifier: Int,
driver: SqlDriver,
fileName: String,
label: String,
query: String,
mapper: (SqlCursor) -> RowType,
): ExecutableQuery {
return SimpleExecutableQuery(identifier, driver, fileName, label, query, mapper)
}
private class SimpleQuery(
private val identifier: Int,
private val queryKeys: Array,
private val driver: SqlDriver,
private val fileName: String,
private val label: String,
private val query: String,
mapper: (SqlCursor) -> RowType,
) : Query(mapper) {
override fun execute(mapper: (SqlCursor) -> R): QueryResult {
return driver.executeQuery(identifier, query, mapper, 0, null)
}
override fun toString() = "$fileName:$label"
override fun addListener(listener: Listener) {
driver.addListener(listener, queryKeys)
}
override fun removeListener(listener: Listener) {
driver.removeListener(listener, queryKeys)
}
}
private class SimpleExecutableQuery(
private val identifier: Int,
private val driver: SqlDriver,
private val fileName: String,
private val label: String,
private val query: String,
mapper: (SqlCursor) -> RowType,
) : ExecutableQuery(mapper) {
override fun execute(mapper: (SqlCursor) -> R): QueryResult {
return driver.executeQuery(identifier, query, mapper, 0, null)
}
override fun toString() = "$fileName:$label"
}
/**
* A listenable, typed query generated by SQLDelight.
*
* @param RowType the type that this query can map its result set to.
*
* @property mapper The mapper this [Query] was created with, which can convert a row in the SQL
* cursor returned by [execute] to [RowType].
*/
abstract class Query(
mapper: (SqlCursor) -> RowType,
) : ExecutableQuery(mapper) {
/**
* Register a listener to be notified of future changes in the result set.
*/
abstract fun addListener(listener: Listener)
/**
* Remove a listener to no longer be notified of future changes in the result set.
*/
abstract fun removeListener(listener: Listener)
/**
* An interface for listening to changes in the result set of a query.
*/
interface Listener {
/**
* Called whenever the query this listener was attached to is dirtied.
*
* Calls are made synchronously on the thread where the updated occurred, after the update applied successfully.
*/
fun queryResultsChanged()
}
}
abstract class ExecutableQuery(
val mapper: (SqlCursor) -> RowType,
) {
/**
* Execute the underlying statement. The resulting cursor is passed to the given block.
*
* The cursor is closed automatically after the block returns.
*/
abstract fun execute(mapper: (SqlCursor) -> R): QueryResult
/**
* @return The result set of the underlying SQL statement as a list of [RowType].
*/
fun executeAsList(): List = execute { cursor ->
val result = mutableListOf()
while (cursor.next()) result.add(mapper(cursor))
result
}.value
/**
* @return The only row of the result set for the underlying SQL statement as a non null
* [RowType].
*
* @throws NullPointerException if when executed this query has no rows in its result set.
* @throws IllegalStateException if when executed this query has multiple rows in its result set.
*/
fun executeAsOne(): RowType {
return executeAsOneOrNull()
?: throw NullPointerException("ResultSet returned null for $this")
}
/**
* @return The first row of the result set for the underlying SQL statement as a non null
* [RowType] or null if the result set has no rows.
*
* @throws IllegalStateException if when executed this query has multiple rows in its result set.
*/
fun executeAsOneOrNull(): RowType? = execute { cursor ->
if (!cursor.next()) return@execute null
val value = mapper(cursor)
check(!cursor.next()) { "ResultSet returned more than 1 row for $this" }
value
}.value
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy