Search code examples
androidsqlkotlinandroid-room

Pre-packaged database has an invalid schema, order mixed up


I'm trying to implement this database with quite a few parameters. Unfortunately I cannot figure out why the order is mixed up that badly. The database is being read from the assets, it's already populated with ~250 items.

Error Message:

Expected:                                                                                     
TableInfo{name='Item', columns={tradingItem3Amount=Column{name='tradingItem3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2Amount=Column{name='itemCrafting2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, description=Column{name='description', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4Amount=Column{name='itemCrafting4Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, buoyancy=Column{name='buoyancy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ItemCategory=Column{name='ItemCategory', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1Amount=Column{name='tradingItem1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3=Column{name='itemCrafting3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4=Column{name='itemCrafting4', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1=Column{name='itemCrafting1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2=Column{name='itemCrafting2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount=Column{name='itemCraftingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, durability=Column{name='durability', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, friction=Column{name='friction', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3Amount=Column{name='itemCrafting3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, imgUrl=Column{name='imgUrl', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1=Column{name='tradingItem1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2=Column{name='tradingItem2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3=Column{name='tradingItem3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, flammable=Column{name='flammable', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1Amount=Column{name='itemCrafting1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2Amount=Column{name='tradingItem2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, modpack=Column{name='modpack', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, extraInfo=Column{name='extraInfo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingAmount=Column{name='tradingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}

                                                                         
Found:
TableInfo{name='Item', columns={Category=Column{name='Category', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Description=Column{name='Description', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3Amount=Column{name='tradingItem3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Name=Column{name='Name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1Amount=Column{name='tradingItem1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3=Column{name='itemCrafting3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4=Column{name='itemCrafting4', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1=Column{name='itemCrafting1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2=Column{name='itemCrafting2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount=Column{name='itemCraftingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, itemCraftingAmount1=Column{name='itemCraftingAmount1', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount2=Column{name='itemCraftingAmount2', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount3=Column{name='itemCraftingAmount3', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount4=Column{name='itemCraftingAmount4', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Durability=Column{name='Durability', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Flammable=Column{name='Flammable', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Bouyancy=Column{name='Bouyancy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ItemID=Column{name='ItemID', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Weight=Column{name='Weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1=Column{name='tradingItem1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2=Column{name='tradingItem2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3=Column{name='tradingItem3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Friction=Column{name='Friction', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2Amount=Column{name='tradingItem2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, modpack=Column{name='modpack', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, extraInfo=Column{name='extraInfo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingAmount=Column{name='tradingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}

The create statement:

This statement is copied from SQLite Browser

CREATE TABLE "Item" (
    "id"    INTEGER,
    "Name"  TEXT,
    "ItemID"    TEXT,
    "Category"  TEXT,
    "Description"   TEXT,
    "Weight"    INTEGER,
    "Durability"    INTEGER,
    "Friction"  INTEGER,
    "Bouyancy"  INTEGER,
    "Flammable" INTEGER,
    "itemCrafting1" TEXT,
    "itemCraftingAmount1"   INTEGER,
    "itemCrafting2" TEXT,
    "itemCraftingAmount2"   INTEGER,
    "itemCrafting3" TEXT,
    "itemCraftingAmount3"   INTEGER,
    "itemCrafting4" TEXT,
    "itemCraftingAmount4"   INTEGER,
    "extraInfo" TEXT,
    "itemCraftingAmount"    INTEGER,
    "tradingAmount" INTEGER,
    "tradingItem1"  TEXT,
    "tradingItem1Amount"    INTEGER,
    "tradingItem2"  TEXT,
    "tradingItem2Amount"    INTEGER,
    "tradingItem3"  TEXT,
    "tradingItem3Amount"    INTEGER,
    "modpack"   TEXT,
    PRIMARY KEY("id")
)

Item.kt

package com.blazecode.scrapguidev2.ui.items

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.blazecode.scrapguidev2.ui.items.enums.Modpack
import com.blazecode.scrapguidev2.ui.items.enums.ItemCategory

@Entity
data class Item(
    @PrimaryKey var id: String = "0",
    @ColumnInfo(name = "name") var name: String?,
    @ColumnInfo(name = "imgUrl") var imgUrl: Int?,
    @ColumnInfo(name = "ItemCategory") var category: ItemCategory?,
    @ColumnInfo(name = "description") var description: String?,
    @ColumnInfo(name = "weight") var weight: Int?,
    @ColumnInfo(name = "durability") var durability: Int?,
    @ColumnInfo(name = "friction") var friction: Int?,
    @ColumnInfo(name = "buoyancy") var buoyancy: Int?,
    @ColumnInfo(name = "flammable") var flammable: Boolean?,

    @ColumnInfo(name = "itemCrafting1") var itemCrafting1: String?,
    @ColumnInfo(name = "itemCrafting2") var itemCrafting2: String?,
    @ColumnInfo(name = "itemCrafting3") var itemCrafting3: String?,
    @ColumnInfo(name = "itemCrafting4") var itemCrafting4: String?,

    @ColumnInfo(name = "itemCrafting1Amount") var itemCrafting1Amount: Int?,
    @ColumnInfo(name = "itemCrafting2Amount") var itemCrafting2Amount: Int?,
    @ColumnInfo(name = "itemCrafting3Amount") var itemCrafting3Amount: Int?,
    @ColumnInfo(name = "itemCrafting4Amount") var itemCrafting4Amount: Int?,

    @ColumnInfo(name = "extraInfo") var extraInfo: String?,
    @ColumnInfo(name = "itemCraftingAmount") var itemCraftingAmount: Int?,

    @ColumnInfo(name = "tradingAmount") var tradingAmount: Int?,
    @ColumnInfo(name = "tradingItem1") var tradingItem1: String?,
    @ColumnInfo(name = "tradingItem1Amount") var tradingItem1Amount: Int?,
    @ColumnInfo(name = "tradingItem2") var tradingItem2: String?,
    @ColumnInfo(name = "tradingItem2Amount") var tradingItem2Amount: Int?,
    @ColumnInfo(name = "tradingItem3") var tradingItem3: String?,
    @ColumnInfo(name = "tradingItem3Amount") var tradingItem3Amount: Int?,

    @ColumnInfo(name = "modpack") var modpack: Modpack?
)

Solution

  • The order is irrelevant, it is not an issue. From a very quick inspection (of the generated SQL - see below) you have an issue with NOT NULL being omitted for the id column. However as explained below comparison/adjustment isn't required as Room generates the exact SQL for the table(s).

    The simple way to ascertain what Room expects (demands in reality) is to

    1. Make the required changes to the @Entity annotated classes.
    2. Include the @Entity annotated classes in the @Database annotated class.
    3. Compile the project (CTRL + F9)
    4. Using the Android View of Android Studio go to the java(generated) and expand it to locate the class that is the same name as the @Database annotated class but suffixed with _Impl.
    5. Locate the createAllTables method and you will see the exact SQL for the creation of the table(s).
      1. Ignore the room_master_table Room will ensure that this is created and populated.

    The following is an example where your code has been added to an existing project (used for other answers):-

    enter image description here