Merge "Remove string query from @RawQuery :'(" into oc-mr1-jetpack-dev am: a5ba9500ad am: e3d3270bc3 am: 1b259b99a0
am: d80ecd10eb

Change-Id: I1d0da65fd33cc8ebdf7a58af721e1b3935891ae3
diff --git a/room/common/src/main/java/android/arch/persistence/room/RawQuery.java b/room/common/src/main/java/android/arch/persistence/room/RawQuery.java
index 46f2193..551416e 100644
--- a/room/common/src/main/java/android/arch/persistence/room/RawQuery.java
+++ b/room/common/src/main/java/android/arch/persistence/room/RawQuery.java
@@ -23,19 +23,15 @@
 
 /**
  * Marks a method in a {@link Dao} annotated class as a raw query method where you can pass the
- * query as a {@link String} or a
- * {@link android.arch.persistence.db.SupportSQLiteQuery SupportSQLiteQuery}.
+ * query as a {@link android.arch.persistence.db.SupportSQLiteQuery SupportSQLiteQuery}.
  * <pre>
  * {@literal @}Dao
  * interface RawDao {
  *     {@literal @}RawQuery
- *     User getUser(String query);
- *     {@literal @}RawQuery
  *     User getUserViaQuery(SupportSQLiteQuery query);
  * }
- * User user = rawDao.getUser("SELECT * FROM User WHERE id = 3 LIMIT 1");
  * SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ? LIMIT 1",
- *         new Object[]{3});
+ *         new Object[]{userId});
  * User user2 = rawDao.getUserViaQuery(query);
  * </pre>
  * <p>
@@ -54,6 +50,10 @@
  * does not return any value, use {@link android.arch.persistence.room.RoomDatabase#query
  * RoomDatabase#query} methods.
  * <p>
+ * RawQuery methods can only be used for read queries. For write queries, use
+ * {@link android.arch.persistence.room.RoomDatabase#getOpenHelper
+ * RoomDatabase.getOpenHelper().getWritableDatabase()}.
+ * <p>
  * <b>Observable Queries:</b>
  * <p>
  * {@code RawQuery} methods can return observable types but you need to specify which tables are
@@ -62,9 +62,10 @@
  * {@literal @}Dao
  * interface RawDao {
  *     {@literal @}RawQuery(observedEntities = User.class)
- *     LiveData&lt;List&lt;User>> getUsers(String query);
+ *     LiveData&lt;List&lt;User>> getUsers(SupportSQLiteQuery query);
  * }
- * LiveData&lt;List&lt;User>> liveUsers = rawDao.getUsers("SELECT * FROM User ORDER BY name DESC");
+ * LiveData&lt;List&lt;User>> liveUsers = rawDao.getUsers(
+ *     new SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));
  * </pre>
  * <b>Returning Pojos:</b>
  * <p>
@@ -83,12 +84,14 @@
  * {@literal @}Dao
  * interface RawDao {
  *     {@literal @}RawQuery
- *     NameAndLastName getNameAndLastName(String query);
+ *     NameAndLastName getNameAndLastName(SupportSQLiteQuery query);
  * }
- * NameAndLastName result = rawDao.getNameAndLastName("SELECT * FROM User WHERE id = 3")
+ * NameAndLastName result = rawDao.getNameAndLastName(
+ *      new SimpleSQLiteQuery("SELECT * FROM User WHERE id = ?", new Object[]{userId}))
  * // or
- * NameAndLastName result = rawDao.getNameAndLastName("SELECT name, lastName FROM User WHERE id =
- * 3")
+ * NameAndLastName result = rawDao.getNameAndLastName(
+ *      new SimpleSQLiteQuery("SELECT name, lastName FROM User WHERE id = ?",
+ *          new Object[]{userId})))
  * </pre>
  * <p>
  * <b>Pojos with Embedded Fields:</b>
@@ -105,10 +108,10 @@
  * {@literal @}Dao
  * interface RawDao {
  *     {@literal @}RawQuery
- *     UserAndPet getUserAndPet(String query);
+ *     UserAndPet getUserAndPet(SupportSQLiteQuery query);
  * }
  * UserAndPet received = rawDao.getUserAndPet(
- *         "SELECT * FROM User, Pet WHERE User.id = Pet.userId LIMIT 1")
+ *         new SimpleSQLiteQuery("SELECT * FROM User, Pet WHERE User.id = Pet.userId LIMIT 1"))
  * </pre>
  *
  * <b>Relations:</b>
@@ -125,9 +128,10 @@
  * {@literal @}Dao
  * interface RawDao {
  *     {@literal @}RawQuery
- *     List&lt;UserAndAllPets> getUsersAndAllPets(String query);
+ *     List&lt;UserAndAllPets> getUsersAndAllPets(SupportSQLiteQuery query);
  * }
- * List&lt;UserAndAllPets> result = rawDao.getUsersAndAllPets("SELECT * FROM users");
+ * List&lt;UserAndAllPets> result = rawDao.getUsersAndAllPets(
+ *      new SimpleSQLiteQuery("SELECT * FROM users"));
  * </pre>
  */
 @Target(ElementType.METHOD)
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
index 9c3fecb..b19c491 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
@@ -22,6 +22,7 @@
 import android.arch.persistence.room.RawQuery
 import android.arch.persistence.room.Update
 import android.arch.persistence.room.ext.RoomTypeNames
+import android.arch.persistence.room.ext.SupportDbTypeNames
 import android.arch.persistence.room.parser.SQLTypeAffinity
 import android.arch.persistence.room.vo.CustomTypeConverter
 import android.arch.persistence.room.vo.Field
@@ -513,4 +514,7 @@
             $typeName does not have these properties, did you mean another class?
             """.trim()
     }
+
+    val RAW_QUERY_STRING_PARAMETER_REMOVED = "RawQuery does not allow passing a string anymore." +
+            " Please use ${SupportDbTypeNames.QUERY}."
 }
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessor.kt
index b26ff6e..2a26419 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessor.kt
@@ -23,6 +23,7 @@
 import android.arch.persistence.room.ext.toListOfClassTypes
 import android.arch.persistence.room.ext.typeName
 import android.arch.persistence.room.parser.SqlParser
+import android.arch.persistence.room.processor.ProcessorErrors.RAW_QUERY_STRING_PARAMETER_REMOVED
 import android.arch.persistence.room.vo.RawQueryMethod
 import com.google.auto.common.AnnotationMirrors
 import com.google.auto.common.MoreElements
@@ -126,9 +127,9 @@
             val stringType = elementUtils.getTypeElement("java.lang.String").asType()
             val isString = types.isAssignable(param, stringType)
             if (isString) {
-                return RawQueryMethod.RuntimeQueryParameter(
-                        paramName = executableElement.parameters[0].simpleName.toString(),
-                        type = stringType.typeName())
+                // special error since this was initially allowed but removed in 1.1 beta1
+                context.logger.e(executableElement, RAW_QUERY_STRING_PARAMETER_REMOVED)
+                return null
             }
         }
         context.logger.e(executableElement, ProcessorErrors.RAW_QUERY_BAD_PARAMS)
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessorTest.kt
index 0a9be4a..cf44304 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/RawQueryMethodProcessorTest.kt
@@ -23,11 +23,11 @@
 import android.arch.persistence.room.PrimaryKey
 import android.arch.persistence.room.Query
 import android.arch.persistence.room.RawQuery
-import android.arch.persistence.room.ext.CommonTypeNames
 import android.arch.persistence.room.ext.PagingTypeNames
 import android.arch.persistence.room.ext.SupportDbTypeNames
 import android.arch.persistence.room.ext.hasAnnotation
 import android.arch.persistence.room.ext.typeName
+import android.arch.persistence.room.processor.ProcessorErrors.RAW_QUERY_STRING_PARAMETER_REMOVED
 import android.arch.persistence.room.testing.TestInvocation
 import android.arch.persistence.room.testing.TestProcessor
 import android.arch.persistence.room.vo.RawQueryMethod
@@ -70,17 +70,8 @@
                 """
                 @RawQuery
                 abstract public int[] foo(String query);
-                """) { query, _ ->
-            assertThat(query.name, `is`("foo"))
-            assertThat(query.runtimeQueryParam, `is`(
-                    RawQueryMethod.RuntimeQueryParameter(
-                            paramName = "query",
-                            type = CommonTypeNames.STRING
-                    )
-            ))
-            assertThat(query.returnType.typeName(),
-                    `is`(ArrayTypeName.of(TypeName.INT) as TypeName))
-        }.compilesWithoutError()
+                """) { _, _ ->
+        }.failsToCompile().withErrorContaining(RAW_QUERY_STRING_PARAMETER_REMOVED)
     }
 
     @Test
@@ -211,7 +202,8 @@
         singleQueryMethod(
                 """
                 @RawQuery
-                abstract public int[] foo(String query, String query2);
+                abstract public int[] foo(SupportSQLiteQuery query,
+                                          SupportSQLiteQuery query2);
                 """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RAW_QUERY_BAD_PARAMS
@@ -223,7 +215,7 @@
         singleQueryMethod(
                 """
                 @RawQuery
-                abstract public int[] foo(String... query);
+                abstract public int[] foo(SupportSQLiteQuery... query);
                 """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.RAW_QUERY_BAD_PARAMS
@@ -235,7 +227,7 @@
         singleQueryMethod(
                 """
                 @RawQuery(observedEntities = {${COMMON.NOT_AN_ENTITY_TYPE_NAME}.class})
-                abstract public int[] foo(String query);
+                abstract public int[] foo(SupportSQLiteQuery query);
                 """) { _, _ ->
         }.failsToCompile().withErrorContaining(
                 ProcessorErrors.rawQueryBadEntity(COMMON.NOT_AN_ENTITY_TYPE_NAME)
@@ -255,7 +247,7 @@
                     public java.util.List<User> users;
                 }
                 @RawQuery(observedEntities = MyPojo.class)
-                abstract public int[] foo(String query);
+                abstract public int[] foo(SupportSQLiteQuery query);
                 """) { method, _ ->
             assertThat(method.observedTableNames, `is`(setOf("User")))
         }.compilesWithoutError()
@@ -271,7 +263,7 @@
                     public User users;
                 }
                 @RawQuery(observedEntities = MyPojo.class)
-                abstract public int[] foo(String query);
+                abstract public int[] foo(SupportSQLiteQuery query);
                 """) { method, _ ->
             assertThat(method.observedTableNames, `is`(setOf("User")))
         }.compilesWithoutError()
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/RawDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/RawDao.java
index ae09350..1487938 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/RawDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/RawDao.java
@@ -32,46 +32,40 @@
 @Dao
 public interface RawDao {
     @RawQuery
-    User getUser(String query);
-
-    @RawQuery
-    UserAndAllPets getUserAndAllPets(String query);
+    UserAndAllPets getUserAndAllPets(SupportSQLiteQuery query);
 
     @RawQuery(observedEntities = UserAndAllPets.class)
-    LiveData<UserAndAllPets> getUserAndAllPetsObservable(String query);
+    LiveData<UserAndAllPets> getUserAndAllPetsObservable(SupportSQLiteQuery query);
 
     @RawQuery
     User getUser(SupportSQLiteQuery query);
 
     @RawQuery
-    UserAndPet getUserAndPet(String query);
+    UserAndPet getUserAndPet(SupportSQLiteQuery query);
 
     @RawQuery
-    NameAndLastName getUserNameAndLastName(String query);
-
-    @RawQuery(observedEntities = User.class)
     NameAndLastName getUserNameAndLastName(SupportSQLiteQuery query);
 
-    @RawQuery
-    int count(String query);
+    @RawQuery(observedEntities = User.class)
+    NameAndLastName getUserNameAndLastNameWithObserved(SupportSQLiteQuery query);
 
     @RawQuery
-    List<User> getUserList(String query);
+    int count(SupportSQLiteQuery query);
 
     @RawQuery
-    List<UserAndPet> getUserAndPetList(String query);
+    List<User> getUserList(SupportSQLiteQuery query);
+
+    @RawQuery
+    List<UserAndPet> getUserAndPetList(SupportSQLiteQuery query);
 
     @RawQuery(observedEntities = UserAndPet.class)
-    LiveData<List<UserAndPet>> getUserAndPetListObservable(String query);
-
-    @RawQuery(observedEntities = User.class)
-    LiveData<User> getUserLiveData(String query);
+    LiveData<List<UserAndPet>> getUserAndPetListObservable(SupportSQLiteQuery query);
 
     @RawQuery(observedEntities = User.class)
     LiveData<User> getUserLiveData(SupportSQLiteQuery query);
 
     @RawQuery
-    UserNameAndBirthday getUserAndBirthday(String query);
+    UserNameAndBirthday getUserAndBirthday(SupportSQLiteQuery query);
 
     class UserNameAndBirthday {
         @ColumnInfo(name = "mName")
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RawQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RawQueryTest.java
index 67f57ed..20afdda0 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RawQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RawQueryTest.java
@@ -53,7 +53,7 @@
 
     @Test
     public void entity_null() {
-        User user = mRawDao.getUser("SELECT * FROM User WHERE mId = 0");
+        User user = mRawDao.getUser(new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = 0"));
         assertThat(user, is(nullValue()));
     }
 
@@ -61,7 +61,8 @@
     public void entity_one() {
         User expected = TestUtil.createUser(3);
         mUserDao.insert(expected);
-        User received = mRawDao.getUser("SELECT * FROM User WHERE mId = 3");
+        User received = mRawDao.getUser(new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = ?",
+                new Object[]{3}));
         assertThat(received, is(expected));
     }
 
@@ -69,7 +70,8 @@
     public void entity_list() {
         List<User> expected = TestUtil.createUsersList(1, 2, 3, 4);
         mUserDao.insertAll(expected.toArray(new User[4]));
-        List<User> received = mRawDao.getUserList("SELECT * FROM User ORDER BY mId ASC");
+        List<User> received = mRawDao.getUserList(
+                new SimpleSQLiteQuery("SELECT * FROM User ORDER BY mId ASC"));
         assertThat(received, is(expected));
     }
 
@@ -84,7 +86,8 @@
 
     @Test
     public void entity_liveData_supportQuery() throws TimeoutException, InterruptedException {
-        liveDataTest(mRawDao.getUserLiveData("SELECT * FROM User WHERE mId = 3"));
+        liveDataTest(mRawDao.getUserLiveData(
+                new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = ?", new Object[]{3})));
     }
 
     private void liveDataTest(
@@ -119,8 +122,8 @@
         Pet[] pets = TestUtil.createPetsForUser(3, 1, 1);
         mUserDao.insert(user);
         mPetDao.insertAll(pets);
-        UserAndPet received = mRawDao.getUserAndPet(
-                "SELECT * FROM User, Pet WHERE User.mId = Pet.mUserId LIMIT 1");
+        UserAndPet received = mRawDao.getUserAndPet(new SimpleSQLiteQuery(
+                "SELECT * FROM User, Pet WHERE User.mId = Pet.mUserId LIMIT 1"));
         assertThat(received.getUser(), is(user));
         assertThat(received.getPet(), is(pets[0]));
     }
@@ -132,7 +135,8 @@
         Pet[] pets = TestUtil.createPetsForUser(3, 1, 10);
         mPetDao.insertAll(pets);
         UserAndAllPets result = mRawDao
-                .getUserAndAllPets("SELECT * FROM User WHERE mId = 3");
+                .getUserAndAllPets(new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = ?",
+                        new Object[]{3}));
         assertThat(result.user, is(user));
         assertThat(result.pets, is(Arrays.asList(pets)));
     }
@@ -142,7 +146,7 @@
         User user = TestUtil.createUser(3);
         mUserDao.insert(user);
         NameAndLastName result =
-                mRawDao.getUserNameAndLastName("SELECT * FROM User");
+                mRawDao.getUserNameAndLastName(new SimpleSQLiteQuery("SELECT * FROM User"));
         assertThat(result, is(new NameAndLastName(user.getName(), user.getLastName())));
     }
 
@@ -151,7 +155,7 @@
         User user = TestUtil.createUser(3);
         mUserDao.insert(user);
         NameAndLastName result =
-                mRawDao.getUserNameAndLastName(new SimpleSQLiteQuery(
+                mRawDao.getUserNameAndLastNameWithObserved(new SimpleSQLiteQuery(
                         "SELECT * FROM User WHERE mId = ?",
                         new Object[]{3}
                 ));
@@ -163,7 +167,7 @@
         User user = TestUtil.createUser(3);
         mUserDao.insert(user);
         RawDao.UserNameAndBirthday result = mRawDao.getUserAndBirthday(
-                "SELECT mName, mBirthday FROM user LIMIT 1");
+                new SimpleSQLiteQuery("SELECT mName, mBirthday FROM user LIMIT 1"));
         assertThat(result.name, is(user.getName()));
         assertThat(result.birthday, is(user.getBirthday()));
     }
@@ -174,7 +178,8 @@
         Pet[] pets = TestUtil.createPetsForUser(3, 1, 1);
         mUserDao.insert(user);
         mPetDao.insertAll(pets);
-        UserAndPet received = mRawDao.getUserAndPet("SELECT * FROM User LIMIT 1");
+        UserAndPet received = mRawDao.getUserAndPet(
+                new SimpleSQLiteQuery("SELECT * FROM User LIMIT 1"));
         assertThat(received.getUser(), is(user));
         assertThat(received.getPet(), is(nullValue()));
     }
@@ -186,8 +191,9 @@
         mUserDao.insertAll(users);
         mPetDao.insertAll(pets);
         List<UserAndPet> received = mRawDao.getUserAndPetList(
-                "SELECT * FROM User LEFT JOIN Pet ON (User.mId = Pet.mUserId)"
-                        + " ORDER BY mId ASC, mPetId ASC");
+                new SimpleSQLiteQuery(
+                        "SELECT * FROM User LEFT JOIN Pet ON (User.mId = Pet.mUserId)"
+                        + " ORDER BY mId ASC, mPetId ASC"));
         assertThat(received.size(), is(3));
         // row 0
         assertThat(received.get(0).getUser(), is(users[0]));
@@ -203,15 +209,15 @@
     @Test
     public void count() {
         mUserDao.insertAll(TestUtil.createUsersArray(3, 5, 7, 10));
-        int count = mRawDao.count("SELECT COUNT(*) FROM User");
+        int count = mRawDao.count(new SimpleSQLiteQuery("SELECT COUNT(*) FROM User"));
         assertThat(count, is(4));
     }
 
     @Test
     public void embedded_liveData() throws TimeoutException, InterruptedException {
         LiveData<List<UserAndPet>> liveData = mRawDao.getUserAndPetListObservable(
-                "SELECT * FROM User LEFT JOIN Pet ON (User.mId = Pet.mUserId)"
-                        + " ORDER BY mId ASC, mPetId ASC");
+                new SimpleSQLiteQuery("SELECT * FROM User LEFT JOIN Pet ON (User.mId = Pet.mUserId)"
+                        + " ORDER BY mId ASC, mPetId ASC"));
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> liveData.observeForever(user -> {
                 })
@@ -251,10 +257,13 @@
         assertThat(liveData.getValue(), is(emptyList()));
     }
 
+    @SuppressWarnings("ConstantConditions")
     @Test
     public void relation_liveData() throws TimeoutException, InterruptedException {
         LiveData<UserAndAllPets> liveData = mRawDao
-                .getUserAndAllPetsObservable("SELECT * FROM User WHERE mId = 3");
+                .getUserAndAllPetsObservable(
+                        new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = ?",
+                                new Object[]{3}));
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> liveData.observeForever(user -> {
                 })