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