1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.room 18 19 /** 20 * Marks a method in a `Dao` annotated class as a query method. 21 * 22 * The value of the annotation includes the query that will be run when this method is called. This 23 * query is **verified at compile time** by Room to ensure that it compiles fine against the 24 * database. 25 * 26 * The arguments of the method will be bound to the bind arguments in the SQL statement. See 27 * [SQLite's binding documentation](https://www.sqlite.org/c3ref/bind_blob.html) for details of bind 28 * arguments in SQLite. 29 * 30 * Room only supports named bind parameter `:name` to avoid any confusion between the method 31 * parameters and the query bind parameters. 32 * 33 * Room will automatically bind the parameters of the method into the bind arguments. This is done 34 * by matching the name of the parameters to the name of the bind arguments. 35 * 36 * ``` 37 * @Query("SELECT * FROM song WHERE release_year = :year") 38 * public abstract fun findSongsByReleaseYear(year: Int): List<Song> 39 * ``` 40 * 41 * As an extension over SQLite bind arguments, Room supports binding a list of parameters to the 42 * query. At runtime, Room will build the correct query to have matching number of bind arguments 43 * depending on the number of items in the method parameter. 44 * 45 * ``` 46 * @Query("SELECT * FROM song WHERE id IN(:songIds)") 47 * public abstract fun findByIds(songIds: Array<Long>): List<Song> 48 * ``` 49 * 50 * For the example above, if the `songIds` is an array of 3 elements, Room will run the query as: 51 * `SELECT * FROM song WHERE id IN(?, ?, ?)` and bind each item in the `songIds` array into the 52 * statement. One caveat of this type of binding is that only 999 items can be bound to the query, 53 * this is a limitation of SQLite 54 * [see Section 9 of SQLite Limits](https://www.sqlite.org/limits.html) 55 * 56 * There are 4 type of statements supported in `Query` methods: SELECT, INSERT, UPDATE, and DELETE. 57 * 58 * For SELECT queries, Room will infer the result contents from the method's return type and 59 * generate the code that will automatically convert the query result into the method's return type. 60 * For single result queries, the return type can be any data object (also known as data classes). 61 * For queries that return multiple values, you can use [java.util.List] or `Array`. In addition to 62 * these, any query may return [android.database.Cursor] or any query result can be wrapped in a 63 * [androidx.lifecycle.LiveData]. 64 * 65 * INSERT queries can return `void` or `Long`. If it is a `Long`, the value is the SQLite rowid of 66 * the row inserted by this query. Note that queries which insert multiple rows cannot return more 67 * than one rowid, so avoid such statements if returning `Long`. 68 * 69 * UPDATE or DELETE queries can return `void` or `Int`. If it is an `Int`, the value is the number 70 * of rows affected by this query. 71 * 72 * **Flow** 73 * 74 * If you are using Kotlin, you can also return `Flow<T>` from query methods. This creates a 75 * `Flow<T>` object that emits the results of the query and re-dispatches the query every time the 76 * data in the queried table changes. 77 * 78 * Note that querying a table with a return type of `Flow<T>` always returns the first row in the 79 * result set, rather than emitting all of the rows in sequence. To observe changes over multiple 80 * rows in a table, use a return type of `Flow<List<T>>` instead. 81 * 82 * Keep nullability in mind when choosing a return type, as it affects how the query method handles 83 * empty tables: 84 * * When the return type is `Flow<T>`, querying an empty table throws a null pointer exception. 85 * * When the return type is `Flow<T?>`, querying an empty table emits a null value. 86 * * When the return type is `Flow<List<T>>`, querying an empty table emits an empty list. 87 * 88 * **RxJava2** 89 * 90 * If you are using RxJava2, you can also return `Flowable<T>` or `Publisher<T>` from query methods. 91 * Since Reactive Streams does not allow `null`, if the query returns a nullable type, it will not 92 * dispatch anything if the value is `null` (like fetching an [Entity] row that does not exist). You 93 * can return [Flowable<T[]>] or [Flowable<List<T>>] to workaround this limitation. 94 * 95 * Both `Flowable<T>` and `Publisher<T>` will observe the database for changes and re-dispatch if 96 * data changes. If you want to query the database without observing changes, you can use `Maybe<T>` 97 * or `Single<T>`. If a `Single<T>` query returns `null`, Room will throw 98 * [androidx.room.EmptyResultSetException]. 99 * 100 * Additionally if the statement is an INSERT, UPDATE or DELETE then the return types, `Single<T>`, 101 * `Maybe<T>` and `Completable` are supported. 102 * 103 * You can return arbitrary data classes from your query methods as long as the properties of the 104 * data class match the column names in the query result. 105 * 106 * For example, if you have class: 107 * ``` 108 * data class SongDuration ( 109 * val name: String, 110 * @ColumnInfo(name = "duration") 111 * val length: String 112 * ) 113 * ``` 114 * 115 * You can write a query like this: 116 * ``` 117 * @Query("SELECT name, duration FROM song WHERE id = :songId LIMIT 1") 118 * public abstract fun findSongDuration(songId: Int): SongDuration 119 * ``` 120 * 121 * And Room will create the correct implementation to convert the query result into a `SongDuration` 122 * object. If there is a mismatch between the query result and the properties of the data class, and 123 * as long as there is at least 1 field match, Room prints a [RoomWarnings.QUERY_MISMATCH] warning 124 * and sets as many properties as it can. 125 */ 126 @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER) 127 @Retention(AnnotationRetention.BINARY) 128 public annotation class Query( 129 /** 130 * The SQLite query to be run. 131 * 132 * @return The query to be run. 133 */ 134 val value: String 135 ) 136