androidandroid-roomandroid-jetpackandroidx

Room DB: What does UPSERT returns?


While @Insert returns Long or collection of it for rowId and @Delete or @Update returns Int for number of rows affected, then what does @Upsert can return?

Reference: https://developer.android.com/training/data-storage/room/accessing-data


Solution

  • The function/method invoked with an @Upsert annotation can return

    1. nothing/void, or
    2. a Long/long, or
    3. an array of Longs/longs (if multiple upserts are possible).

    It is easy enough to ascertain by coding and compiling

    e.g. using

    @Upsert
    fun upsert(parent: PartCargo): Int
    

    Fails top compile with Not sure how to handle upsert method's return type.

    Whilst

    @Upsert
    fun upsert(parent: PartCargo): Long
    
    @Upsert
    fun upsert(parent: PartCargo)
    

    and

    compile successfully.

    However

    @Upsert
    fun upsert(parent: PartCargo): LongArray
    

    Fails with Upsert method accepts a single parameter but the return type is a collection of elements.

    Whilst

    @Upsert
    fun upsert(parents: List<PartCargo>): LongArray
    

    Compiles successfully.

    Additional

    can you add a reference about Room's implementation of Upsert that behind the scene only do insert and replace before I accept this answer?

    A reference, if there is one, is not necessary. What is actually done "behind the scenes" can easily be established.

    The "behind the scenes", is the annotation processer generating java code when compiling. This java generated java code forms part of the package and is what is actually used at runtime.

    The 2 core/primary annotations are the @Database and @Dao annotations. These determine the resultant classes that contain the respective generated java. The classes will be the name of the class/interface being processed suffixed with _Impl.

    The generated java is placed with a subfolder of the folder, that via Android View in Android Studio appears as Java(Generated). There will typically be two sub-folders with the same name. One will be seen to contain the respective classes that have been generated.

    e.g. the code extracts above were taken from the following:-

    enter image description here

    The extracts were from the @Dao annotated interface interface DetailsDAO .... and hence the DetailsDAO_Impl class that has been generated.

    A search on Upsert locates:-

    enter image description here

    It is then just a matter of ascertaining the respective code utilised and the SQL invoked. For the above the eventual respective code is:-

    this.__insertionAdapterOfPartCargo = new EntityInsertionAdapter<PartCargo>(__db) {
          @Override
          @NonNull
          protected String createQuery() {
            return "INSERT OR REPLACE INTO `parts` (`tId`,`detailsTId`,`id`,`name`) VALUES (nullif(?, 0),?,?,?)";
          }