1 /* 2 * Copyright 2018 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 import java.lang.annotation.ElementType; 20 import java.lang.annotation.Retention; 21 import java.lang.annotation.RetentionPolicy; 22 import java.lang.annotation.Target; 23 24 /** 25 * Marks a method in a {@link Dao} annotated class as a raw query method where you can pass the 26 * query as a {@link androidx.sqlite.db.SupportSQLiteQuery SupportSQLiteQuery}. 27 * <pre> 28 * {@literal @}Dao 29 * interface RawDao { 30 * {@literal @}RawQuery 31 * User getUserViaQuery(SupportSQLiteQuery query); 32 * } 33 * SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ? LIMIT 1", 34 * new Object[]{userId}); 35 * User user2 = rawDao.getUserViaQuery(query); 36 * </pre> 37 * <p> 38 * Room will generate the code based on the return type of the function and failure to 39 * pass a proper query will result in a runtime failure or an undefined result. 40 * <p> 41 * If you know the query at compile time, you should always prefer {@link Query} since it validates 42 * the query at compile time and also generates more efficient code since Room can compute the 43 * query result at compile time (e.g. it does not need to account for possibly missing columns in 44 * the response). 45 * <p> 46 * On the other hand, {@code RawQuery} serves as an escape hatch where you can build your own 47 * SQL query at runtime but still use Room to convert it into objects. 48 * <p> 49 * {@code RawQuery} methods must return a non-void type. If you want to execute a raw query that 50 * does not return any value, use {@link androidx.room.RoomDatabase#query 51 * RoomDatabase#query} methods. 52 * <p> 53 * RawQuery methods can only be used for read queries. For write queries, use 54 * {@link androidx.room.RoomDatabase#getOpenHelper 55 * RoomDatabase.getOpenHelper().getWritableDatabase()}. 56 * <p> 57 * <b>Observable Queries:</b> 58 * <p> 59 * {@code RawQuery} methods can return observable types but you need to specify which tables are 60 * accessed in the query using the {@link #observedEntities()} field in the annotation. 61 * <pre> 62 * {@literal @}Dao 63 * interface RawDao { 64 * {@literal @}RawQuery(observedEntities = User.class) 65 * LiveData<List<User>> getUsers(SupportSQLiteQuery query); 66 * } 67 * LiveData<List<User>> liveUsers = rawDao.getUsers( 68 * new SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC")); 69 * </pre> 70 * <b>Returning Pojos:</b> 71 * <p> 72 * RawQueries can also return plain old java objects, similar to {@link Query} methods. 73 * <pre> 74 * public class NameAndLastName { 75 * public final String name; 76 * public final String lastName; 77 * 78 * public NameAndLastName(String name, String lastName) { 79 * this.name = name; 80 * this.lastName = lastName; 81 * } 82 * } 83 * 84 * {@literal @}Dao 85 * interface RawDao { 86 * {@literal @}RawQuery 87 * NameAndLastName getNameAndLastName(SupportSQLiteQuery query); 88 * } 89 * NameAndLastName result = rawDao.getNameAndLastName( 90 * new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ?", new Object[]{userId})) 91 * // or 92 * NameAndLastName result = rawDao.getNameAndLastName( 93 * new SimpleSQLiteQuery("SELECT name, lastName FROM User WHERE id = ?", 94 * new Object[]{userId}))) 95 * </pre> 96 * <p> 97 * <b>Pojos with Embedded Fields:</b> 98 * <p> 99 * {@code RawQuery} methods can return pojos that include {@link Embedded} fields as well. 100 * <pre> 101 * public class UserAndPet { 102 * {@literal @}Embedded 103 * public User user; 104 * {@literal @}Embedded 105 * public Pet pet; 106 * } 107 * 108 * {@literal @}Dao 109 * interface RawDao { 110 * {@literal @}RawQuery 111 * UserAndPet getUserAndPet(SupportSQLiteQuery query); 112 * } 113 * UserAndPet received = rawDao.getUserAndPet( 114 * new SimpleSQLiteQuery("SELECT * FROM User, Pet WHERE User.id = Pet.userId LIMIT 1")) 115 * </pre> 116 * 117 * <b>Relations:</b> 118 * <p> 119 * {@code RawQuery} return types can also be objects with {@link Relation Relations}. 120 * <pre> 121 * public class UserAndAllPets { 122 * {@literal @}Embedded 123 * public User user; 124 * {@literal @}Relation(parentColumn = "id", entityColumn = "userId") 125 * public List<Pet> pets; 126 * } 127 * 128 * {@literal @}Dao 129 * interface RawDao { 130 * {@literal @}RawQuery 131 * List<UserAndAllPets> getUsersAndAllPets(SupportSQLiteQuery query); 132 * } 133 * List<UserAndAllPets> result = rawDao.getUsersAndAllPets( 134 * new SimpleSQLiteQuery("SELECT * FROM users")); 135 * </pre> 136 */ 137 @Target(ElementType.METHOD) 138 @Retention(RetentionPolicy.CLASS) 139 public @interface RawQuery { 140 /** 141 * Denotes the list of entities which are accessed in the provided query and should be observed 142 * for invalidation if the query is observable. 143 * <p> 144 * The listed classes should either be annotated with {@link Entity} or they should reference to 145 * at least 1 Entity (via {@link Embedded} or {@link Relation}). 146 * <p> 147 * Providing this field in a non-observable query has no impact. 148 * <pre> 149 * {@literal @}Dao 150 * interface RawDao { 151 * {@literal @}RawQuery(observedEntities = User.class) 152 * LiveData<List<User>> getUsers(String query); 153 * } 154 * LiveData<List<User>> liveUsers = rawDao.getUsers("select * from User ORDER BY name 155 * DESC"); 156 * </pre> 157 * 158 * @return List of entities that should invalidate the query if changed. 159 */ observedEntities()160 Class[] observedEntities() default {}; 161 } 162