Fail when non-null fields are missing in query
This CL change Room query verification to fail IF one of
the missing columns is annotated with @NonNull. It is
probably un-intended by the developer so it is better
to fail instead of a warning.
Bug: 67115337
Test: QueryMethodProcessorTest#pojo_missingNonNull
Change-Id: I22bd5797eb5fbc22d0dd242683cbbdf0c60457db
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 2ab0182..8058ff9 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
@@ -199,6 +199,16 @@
""".trim()
}
+ fun pojoMissingNonNull(pojoTypeName: TypeName, missingPojoFields: List<String>,
+ allQueryColumns: List<String>) : String {
+ return """
+ The columns returned by the query does not have the fields
+ [${missingPojoFields.joinToString(",")}] in $pojoTypeName even though they are
+ annotated as non-null or primitive.
+ Columns returned by the query: [${allQueryColumns.joinToString(",")}]
+ """.trim()
+ }
+
fun cursorPojoMismatch(pojoTypeName: TypeName,
unusedColumns: List<String>, allColumns: List<String>,
unusedFields: List<Field>, allFields: List<Field>): String {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
index 062b179..a013dc7 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
@@ -19,7 +19,6 @@
import android.arch.persistence.room.ext.L
import android.arch.persistence.room.ext.S
import android.arch.persistence.room.ext.T
-import android.arch.persistence.room.ext.typeName
import android.arch.persistence.room.processor.Context
import android.arch.persistence.room.processor.ProcessorErrors
import android.arch.persistence.room.solver.CodeGenScope
@@ -71,6 +70,13 @@
)
context.logger.w(Warning.CURSOR_MISMATCH, null, warningMsg)
}
+ val nonNulls = remainingFields.filter { it.nonNull }
+ if (nonNulls.isNotEmpty()) {
+ context.logger.e(ProcessorErrors.pojoMissingNonNull(
+ pojoTypeName = pojo.typeName,
+ missingPojoFields = nonNulls.map { it.name },
+ allQueryColumns = info.columns.map { it.name }))
+ }
if (matchedFields.isEmpty()) {
context.logger.e(ProcessorErrors.CANNOT_FIND_QUERY_RESULT_ADAPTER)
}
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
index 7e892b7..a2cb768 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
@@ -70,6 +70,7 @@
companion object {
const val DAO_PREFIX = """
package foo.bar;
+ import android.support.annotation.NonNull;
import android.arch.persistence.room.*;
@Dao
abstract class MyClass {
@@ -599,6 +600,30 @@
}
@Test
+ fun pojo_missingNonNull() {
+ pojoTest("""
+ @NonNull
+ String name;
+ String lastName;
+ """, listOf("lastName")) { adapter, _, _ ->
+ assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
+ assertThat(adapter?.mapping?.unusedFields, `is`(
+ adapter?.pojo?.fields?.filter { it.name == "name" }
+ ))
+ }?.failsToCompile()?.withWarningContaining(
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = emptyList(),
+ unusedFields = listOf(createField("name")),
+ allColumns = listOf("lastName"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ ))?.and()?.withErrorContaining(
+ ProcessorErrors.pojoMissingNonNull(pojoTypeName = POJO,
+ missingPojoFields = listOf("name"),
+ allQueryColumns = listOf("lastName")))
+ }
+
+ @Test
fun pojo_tooManyFieldsAndColumns() {
pojoTest("""
String name;
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
index 7bb137f..18e8d93 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
@@ -35,16 +35,16 @@
@Query("SELECT * from School WHERE address_street LIKE '%' || :street || '%'")
public abstract List<School> findByStreet(String street);
- @Query("SELECT mName, manager_mName FROM School")
+ @Query("SELECT mId, mName, manager_mName FROM School")
public abstract List<School> schoolAndManagerNames();
- @Query("SELECT mName, manager_mName FROM School")
+ @Query("SELECT mId, mName, manager_mName FROM School")
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
public abstract List<SchoolRef> schoolAndManagerNamesAsPojo();
@Query("SELECT address_lat as lat, address_lng as lng FROM School WHERE mId = :schoolId")
public abstract Coordinates loadCoordinates(int schoolId);
- @Query("SELECT address_lat, address_lng FROM School WHERE mId = :schoolId")
+ @Query("SELECT mId, address_lat, address_lng FROM School WHERE mId = :schoolId")
public abstract School loadCoordinatesAsSchool(int schoolId);
}