Status Update
Comments
au...@google.com <au...@google.com>
el...@google.com <el...@google.com> #2
aa...@gmail.com <aa...@gmail.com> #3
Sure, something like this:
@Entity(tableName = "Album")
data class Album(
@PrimaryKey
val id: Long,
val artistId: Long,
val albumName: String,
)
@Entity(tableName = "Artist")
data class Artist(
@PrimaryKey
val id: Long,
val name: String,
)
Lets say we have three artists, but only two have an album in the Albums table:
Artists:
id | name |
---|---|
1 | Artist 1 |
2 | Artist 2 |
3 | Artist 3 |
Albums:
id | artistId | albumName |
---|---|---|
1 | 1 | Album 1 |
2 | 2 | Album 2 |
A standard JOIN query would return only Artist 1
and Artist 2
and not Artist 3
as there are no albums for that artist:
@Query("SELECT * FROM Artist JOIN Album ON Artist.id = Album.artistId")
fun getArtistAndAlbums(): Map<Artist, List<Album>>
A left join doesn't work because the current implementation tries to generate Album
objects for Artist 3
but this artist doesn't have any and thus the values are null
, which Kotlin doesn't allow.
@Query("SELECT * FROM Artist LEFT JOIN Album ON Artist.id = Album.artistId")
fun getArtistAndAlbums(): Map<Artist, List<Album>>
el...@google.com <el...@google.com>
ap...@google.com <ap...@google.com> #4
Branch: androidx-main
commit 9c9bee19b3eec9b7d39715b67798dc0b420f5473
Author: Elif Bilgin <elifbilgin@google.com>
Date: Thu Oct 28 10:11:58 2021
Resolving issue in relational query methods occurring specifically in LEFT JOIN queries.
The issue here arises when the query result adapters create empty value objects for the key-value pairs when the value is not found in the cursor. This results in invalid entries in maps in both 1-1 and 1-many relations, where a valid key is mapped to basically an object where all of its fields are null. This fix implements an additional column null check on the value object's columns and avoids adding the entry to the map if any null columns are found.
In the case where a 1-many mapping is present, the collection returned for a key will not include the invalid value object if it is not found in the cursor. If no valid values are found, then a key will be mapped to an empty collection.
Test: Added test cases for a 1-1 and 1-many mapping of a left join MultimapQueryTest.java.
Bug: 201946438
Change-Id: Id5552b9a7766e43f9d0434d7e5d6aff9dc84afb5
M room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MultimapQueryResultAdapter.kt
M room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/GuavaImmutableMultimapQueryResultAdapter.kt
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultimapQueryTest.java
M room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/SingleNamedColumnRowAdapter.kt
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/MusicDao.java
M room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/vo/Album.java
M room/room-compiler/src/main/kotlin/androidx/room/solver/query/result/MapQueryResultAdapter.kt
mr...@crossway.org <mr...@crossway.org> #5
What is the expected way of calling the above sample from Kotlin after this fix? Do we need a nullable parameterized type like below?
@Query("SELECT * FROM Artist LEFT JOIN Album ON Artist.id = Album.artistId")
fun getArtistAndAlbums(): Map<Artist, List<Album?>>
I have a database schema similar to the one above, but I am getting a crash on a non-null intrinsics check from the DAO, whether I use a nullable parameterized type or not. I also tried ksp instead of kapt and I am still seeing the same issue.
mr...@crossway.org <mr...@crossway.org> #6
Ah sorry, bad report. After looking at the generated file a bit closer I realized that the problem was a slightly different one. I will file a separate bug report.
Description
Artifact used : Room Version used: 2.4.0-alpha05 Devices/Android versions reproduced on: Emulator
This is more of a feature request, but trying out the new multimap feature I'm having issues with LEFT JOIN queries.
Take this example from the release notes (One-to-Many relationship):
Let's say we want all artists, regardless if they have any albums. So we change the query to use a LEFT JOIN:
This won't work if we have an
Artist
without albums, ifAlbum
doesn't have any nullable fields. Because the current implementation will always try and generate an Album object.Is it possible to let Room return an empty list of 'Albums' in that case? Or
Map<Artist, List<Album>?>
?Thanks for your time!