RawQuery.kt
/*
* Copyright 2018 The Android Open Source Project
*
* 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 androidx.room
import kotlin.reflect.KClass
/**
* Marks a method in a [Dao] annotated class as a raw query method where you can pass the
* query as a [androidx.sqlite.db.SupportSQLiteQuery].
*
* ```
* @Dao
* interface RawDao {
* @RawQuery
* getSongViaQuery(query: SupportSQLiteQuery): Song
* }
*
* // Usage of RawDao
* val query = SimpleSQLiteQuery(
* "SELECT * FROM Song WHERE id = ? LIMIT 1",
* arrayOf<Any>(songId)
* )
* val song = rawDao.getSongViaQuery(query)
* ```
*
* Room will generate the code based on the return type of the function and failure to
* pass a proper query will result in a runtime failure or an undefined result.
*
* If you know the query at compile time, you should always prefer [Query] since it validates
* the query at compile time and also generates more efficient code since Room can compute the
* query result at compile time (e.g. it does not need to account for possibly missing columns in
* the response).
*
* On the other hand, `RawQuery` serves as an escape hatch where you can build your own
* SQL query at runtime but still use Room to convert it into objects.
*
* `RawQuery` methods must return a non-void type. If you want to execute a raw query that
* does not return any value, use [androidx.room.RoomDatabase.query] methods.
*
* RawQuery methods can only be used for read queries. For write queries, use
* [androidx.room.RoomDatabase.getOpenHelper].
*
* **Observable Queries:**
*
* `RawQuery` methods can return observable types but you need to specify which tables are
* accessed in the query using the [observedEntities] field in the annotation.
*
* ```
* @Dao
* interface RawDao {
* @RawQuery(observedEntities = Song::class)
* fun getSongs(query: SupportSQLiteQuery): LiveData<List<Song>>
* }
*
* // Usage of RawDao
* val liveSongs = rawDao.getSongs(
* SimpleSQLiteQuery("SELECT * FROM song ORDER BY name DESC")
* )
* ```
*
* **Returning POJOs:**
*
* RawQueries can also return plain old java objects, similar to [Query] methods.
*
* ```
* data class NameAndReleaseYear (
* val name: String,
* @ColumnInfo(name = "release_year")
* val year: Int
* )
*
* @Dao
* interface RawDao {
* @RawQuery
* fun getNameAndReleaseYear(query: SupportSQLiteQuery): NameAndReleaseYear
* }
*
* // Usage of RawDao
* val result: NameAndReleaseYear = rawDao.getNameAndReleaseYear(
* SimpleSQLiteQuery("SELECT * FROM song WHERE id = ?", arrayOf<Any>(songId)))
* ```
*
* **POJOs with Embedded Fields:**
*
* `RawQuery` methods can return POJOs that include [Embedded] fields as well.
* ```
* data class SongAndArtist (
* @Embedded
* val song: Song,
* @Embedded
* val artist: Artist
* )
*
* @Dao
* interface RawDao {
* @RawQuery
* fun getSongAndArtist(query: SupportSQLiteQuery): SongAndArtist
* }
*
* // Usage of RawDao
* val result: = rawDao.getSongAndArtist(
* SimpleSQLiteQuery("SELECT * FROM Song, Artist WHERE Song.artistId = Artist.id LIMIT 1"))
* ```
*
* **Relations:**
*
* `RawQuery` return types can also be objects with [Relation].
* ```
* data class AlbumAndSongs {
* @Embedded
* public val album: Album,
* @Relation(parentColumn = "id", entityColumn = "albumId")
* public val pets: List<Song>
* }
*
* @Dao
* interface RawDao {
* @RawQuery
* fun getAlbumAndSongs(query: SupportSQLiteQuery): List<AlbumAndSongs>
* }
*
* // Usage of RawDao
* val result: = rawDao.getAlbumAndSongs(
* SimpleSQLiteQuery("SELECT * FROM album")
* ): List<AlbumAndSongs>
* ```
*/
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
public annotation class RawQuery(
/**
* Denotes the list of entities which are accessed in the provided query and should be observed
* for invalidation if the query is observable.
*
* The listed classes should either be annotated with [Entity] or they should reference to
* at least 1 [Entity] (via [Embedded] or [Relation]).
*
* Providing this field in a non-observable query has no impact.
*
* ```
* @Dao
* interface RawDao {
* @RawQuery(observedEntities = Song::class)
* fun getUsers(query: String): LiveData<List<User>>
* }
* val liveSongs: = rawDao.getUsers(
* "SELECT * FROM song ORDER BY name DESC")
* ```
*
* @return List of entities that should invalidate the query if changed.
*/
val observedEntities: Array<KClass<*>> = []
)