1. Are you ready for the Galaxy S20? Here is everything we know so far!

Issue with writing Room migration even for just adding a new (empty) table to an existing database

Discussion in 'Android Development' started by Damon Getsman, Apr 3, 2019.

  1. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    This is the third time that I've attempted to write a migration in order to update my database layout with Room (in java). The first two times I ended up just giving up, because no matter what I tried I couldn't get anything to work. I was in a place, previously, where I could just allow a destructive migration, instead, but at this point in development I really need a working migration; I do not want to have to rely on destructive migrations with the amount of data that I currently have in the database. I mean it's not distributed yet, so there aren't other users that'd have to deal with the fallout, but I know I need to learn how do to it The Right Way(tm) anyway, so I'm persisting in working on this migration until it happens, or until I've learned that it's just impossible with Room, which hopefully is not the case. I doubt it would've been recommended to me on #android-dev in the first place if such were the case, though I've found a lot of people that are urging me away from it now due to issues like this that seem to be a bit more common than I would like.

    So my problem is fairly simple to describe, at least. I've got an existing database with a couple of tables that are working just fine, but I need to add a new table for some features that are now up on the implementation list. Oh, and I have updated to the latest version of Room, which is (if I'm not mistaken) 1.1.1 currently.

    The new table (UsualSuspects.java) that I'm trying to add follows (er well the class that implements it, anyway):

    Code (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.arch.persistence.room.ColumnInfo;
    5. import android.arch.persistence.room.Entity;
    6. import android.arch.persistence.room.PrimaryKey;
    7.  
    8. @Entity(tableName="UsualSuspect")
    9. public class UsualSuspect {
    10.     @PrimaryKey(autoGenerate = true)
    11.     private int         id;
    12.     @ColumnInfo(name="name")
    13.     private String      name;
    14.     @ColumnInfo(name="sid")
    15.     private int         sid;
    16.     @ColumnInfo(name="dosage")
    17.     private float       dosage;
    18.     @ColumnInfo(name="notes")
    19.     private String      notes;
    20.  
    21.     public int getId() {
    22.         return id;
    23.     }
    24.  
    25.     public void setId(int id) {
    26.         this.id = id;
    27.     }
    28.  
    29.     public String getName() {
    30.         return name;
    31.     }
    32.  
    33.     public void setName(String name) {
    34.         this.name = name;
    35.     }
    36.  
    37.     public int getSid() {
    38.         return sid;
    39.     }
    40.  
    41.     public void setSid(int sid) {
    42.         this.sid = sid;
    43.     }
    44.  
    45.     public float getDosage() {
    46.         return dosage;
    47.     }
    48.  
    49.     public void setDosage(float dosage) {
    50.         this.dosage = dosage;
    51.     }
    52.  
    53.     public String getNotes() {
    54.         return notes;
    55.     }
    56.  
    57.     public void setNotes(String notes) {
    58.         this.notes = notes;
    59.     }
    60.  
    61.     public UsualSuspect() { }
    62. }
    63.  
    AppDatabase code, including the new migration, follows:
    Code (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.arch.persistence.db.SupportSQLiteDatabase;
    5. import android.arch.persistence.room.Database;
    6. import android.arch.persistence.room.Room;
    7. import android.arch.persistence.room.RoomDatabase;
    8. import android.arch.persistence.room.TypeConverters;
    9. import android.arch.persistence.room.migration.Migration;
    10. import android.content.Context;
    11.  
    12. @Database(entities = {Substance.class, Usage.class, UsualSuspect.class}, version = 4)
    13. @TypeConverters({Converters.class})
    14. public abstract class AppDatabase extends RoomDatabase {
    15.     private static AppDatabase INSTANCE;
    16.  
    17.     public abstract SubstanceDao getSubstanceDao();
    18.     public abstract UsageDao getUsageDao();
    19.     public abstract UsualSuspectDao getUsualSuspectDao();
    20.  
    21.     public static AppDatabase getDatabase(Context ctxt) {
    22.         if (INSTANCE == null) {
    23.             INSTANCE = Room.databaseBuilder(ctxt.getApplicationContext(), AppDatabase.class,
    24.                                             GlobalMisc.DbName)
    25.                     .allowMainThreadQueries()
    26.                     //.fallbackToDestructiveMigration()
    27.                     //.addMigrations(MIGRATION_2_3)
    28.                     .addMigrations(MIGRATION_3_4)
    29.                     .build();
    30.         }
    31.         return INSTANCE;
    32.     }
    33.  
    34.     static final Migration MIGRATION_3_4 = new Migration(3, 4) {
    35.         @Override
    36.         public void migrate(SupportSQLiteDatabase database) {
    37.             database.execSQL("CREATE TABLE IF NOT EXISTS `UsualSuspect` (`id` INTEGER, `sid` " +
    38.                     "INTEGER NOT NULL, `dosage` REAL NOT NULL, `notes` VARCHAR NOT NULL, " +
    39.                     "PRIMARY KEY (`id`))");
    40.         }
    41.     };
    42.  
    43.     public static void destroyInstance() { INSTANCE = null; }
    44. }
    45.  
    When I'm attempting to run the application with the following migration, I'm receiving the following error from Room (forgive the lack of a full stack trace, I'll run it again and include that at the end here, though I do believe this is the applicable bit from it:
    Code (Text):
    1.  
    2. Expected:
    3.     TableInfo{name='UsualSuspect', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, notes=Column{name='notes', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    4.  
    5. Found:
    6.     TableInfo{name='UsualSuspect', columns={dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, notes=Column{name='notes', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, name=Column{name='name', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    7.  
    As you can see, the only discrepancy (as far as I can tell) between what is expected and what is found is that the columns are arranged differently; however, I can't for the life of me find where that is echoed in the code that I've written. I'm really not sure where on earth to go with this next.

    In case it's necessary, the following snippets (in order) are for UsualSuspectDbase and UsualSuspectDao:
    Code (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.arch.persistence.room.Database;
    5. import android.arch.persistence.room.RoomDatabase;
    6.  
    7. @Database(entities = {UsualSuspect.class}, version = 1)
    8. public abstract class UsualSuspectDbase extends RoomDatabase {
    9.     public abstract UsualSuspectDao usualSuspectDao();
    10. }
    11.  
    Code (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.arch.persistence.room.Dao;
    5. import android.arch.persistence.room.Query;
    6.  
    7. import java.util.List;
    8.  
    9. @Dao
    10. public interface UsualSuspectDao {
    11.     @Query("SELECT * FROM UsualSuspect")
    12.     List<UsualSuspect> getAll();
    13. }
    14.  
    I would be very grateful for any help that anyone might be able to offer in how I can go about fixing this issue, or some good resources that would spell it out to me a little bit better than what I've found already. I've looked at a ton of google hits already on StackExchange and the like and I'm not able to find anything that's helped so far. Also grateful for any other pointers in the right direction, though honestly I really don't want to try to rewrite this application with something other than Room ORM unless it's absolutely the only way to do it. I'm still kind of an Android environment newbie, and I don't want to have to try to learn a whole different ORM (provided some exist) unless there's no other route to go.

    I'm very grateful for any assistance, as I've said, and thank you in advance for anything that you might have to offer. Please let me know if more information is necessary in order to track down this bug appropriately and I'll get it up as soon as I can. TIA

     


  2. Best Answer:
    Post #19 by Deleted User, Apr 6, 2019 (2 points)
  3. Deleted User

    Deleted User Guest

    On first glance you seem to be doing everything by the book. Must say I've only had cursory experience with Room. To me it looked like a good system, but I didn't really take it as far as the migration process.
    That error does look quite weird, in particular this looks as if something got screwed up in the parsing. This doesn't look right at all -

    Code (Text):
    1.  
    2. columns={name=Column{name='name',....
    3.  
    A stack trace may shed some more light on it.

    Worst case, you may have to debug into the migration methods, like addMigrations() and even build(), to see exactly what it's doing.

    Another approach you could try is to simplify the upgrade. Pare it back to the simplest possible scenario, just a very simple table definition. Does it work? Build things up from there and see when it goes wrong.
     
    #2 Deleted User, Apr 4, 2019
    Last edited by a moderator: Apr 4, 2019
    GameTheory likes this.
  4. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    So this is what I got from the Debug->Console view in Android Studio. It's missing a bit of the stack trace, I believe; can anybody tell me how to get those '... 9 more' that it's talking about? I'd greatly appreciate it. I'm still kind of a newb for developing in this particular environment.

    Code (Text):
    1.  
    2. E/AndroidRuntime: FATAL EXCEPTION: main
    3.     Process: com.example.sprite.half_lifetimer, PID: 18130
    4.     java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sprite.half_lifetimer/com.example.sprite.half_lifetimer.SubData}: java.lang.IllegalStateException: Migration didn't properly handle UsualSuspect(com.example.sprite.half_lifetimer.UsualSuspect).
    5.      Expected:
    6.     TableInfo{name='UsualSuspect', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, notes=Column{name='notes', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    7.      Found:
    8.     TableInfo{name='UsualSuspect', columns={dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, notes=Column{name='notes', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, name=Column{name='name', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    9.         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2858)
    10.         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2933)
    11.         at android.app.ActivityThread.-wrap11(Unknown Source:0)
    12.         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1612)
    13.         at android.os.Handler.dispatchMessage(Handler.java:105)
    14.         at android.os.Looper.loop(Looper.java:164)
    15.         at android.app.ActivityThread.main(ActivityThread.java:6710)
    16.         at java.lang.reflect.Method.invoke(Native Method)
    17.         at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    18.         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
    19.      Caused by: java.lang.IllegalStateException: Migration didn't properly handle UsualSuspect(com.example.sprite.half_lifetimer.UsualSuspect).
    20.      Expected:
    21.     TableInfo{name='UsualSuspect', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, notes=Column{name='notes', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    22.      Found:
    23.     TableInfo{name='UsualSuspect', columns={dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, notes=Column{name='notes', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, name=Column{name='name', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    24.         at com.example.sprite.half_lifetimer.AppDatabase_Impl$1.validateMigration(AppDatabase_Impl.java:114)
    25.         at android.arch.persistence.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:87)
    26.         at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:133)
    27.         at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:302)
    28.         at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:194)
    29.         at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
    30. E/AndroidRuntime:     at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
    31.         at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:233)
    32.         at com.example.sprite.half_lifetimer.SubstanceDao_AppDatabase_Impl.getAll(SubstanceDao_AppDatabase_Impl.java:147)
    33.         at com.example.sprite.half_lifetimer.Permanence.loadSubstances(Permanence.java:39)
    34.         at com.example.sprite.half_lifetimer.SubData.onCreate(SubData.java:82)
    35.         at android.app.Activity.performCreate(Activity.java:6982)
    36.         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
    37.         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2811)
    38.             ... 9 more
    39.  
    40.         at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
    41.         at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1612)
    42.         at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
    43.         at void android.os.Looper.loop() (Looper.java:164)
    44.         at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6710)
    45.         at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    46.         at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:240)
    47.         at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:770)
    48. I/zygote64: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
    49.         at void android.support.v4.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, android.support.v4.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203)
    50.         at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637)
    51.         at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
    52.         at void android.support.v7.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
    53.         at void android.support.v7.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
    54.         at void com.example.sprite.half_lifetimer.SubData.onCreate(android.os.Bundle) (SubData.java:41)
    55.         at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6982)
    56.         at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1214)
    57.         at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2811)
    58.         at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2933)
    59.         at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
    60.         at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1612)
    61.         at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
    62.         at void android.os.Looper.loop() (Looper.java:164)
    63.         at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6710)
    64.         at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    65.         at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:240)
    66.         at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:770)
    67.     Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/base.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_dependencies_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_resources_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_0_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_1_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_2_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_3_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_4_apk.apk", zip file "/data/app/com.example.sprite.half_
    68.         at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93)
    69.         at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
    70.         at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
    71.         at void android.support.v4.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, android.support.v4.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203)
    72.         at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637)
    73.         at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
    74.         at void android.support.v7.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
    75.         at void android.support.v7.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
    76.         at void com.example.sprite.half_lifetimer.SubData.onCreate(android.os.Bundle) (SubData.java:41)
    77.         at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6982)
    78.         at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1214)
    79.         at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2811)
    80.         at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2933)
    81.         at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
    82.         at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1612)
    83.         at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
    84.         at void android.os.Looper.loop() (Looper.java:164)
    85.         at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6710)
    86.         at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    87.         at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:240)
    88.         at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:770)
    89. I/zygote64: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKeyEventListenerWrapper>: java.lang.NoClassDefFoundError: Failed resolution of: Landroid/view/View$OnUnhandledKeyEventListener;
    90.         at void android.support.v4.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, android.support.v4.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203)
    91.         at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637)
    92.         at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
    93.         at void android.support.v7.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
    94.         at void android.support.v7.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
    95.         at void com.example.sprite.half_lifetimer.SubData.onCreate(android.os.Bundle) (SubData.java:41)
    96.         at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6982)
    97.         at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1214)
    98.         at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2811)
    99.         at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2933)
    100.         at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
    101.         at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1612)
    102.         at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
    103.         at void android.os.Looper.loop() (Looper.java:164)
    104.         at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6710)
    105.         at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    106.         at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:240)
    107.         at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:770)
    108.     Caused by: java.lang.ClassNotFoundException: Didn't find class "android.view.View$OnUnhandledKeyEventListener" on path: DexPathList[[zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/base.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_dependencies_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_resources_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_0_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_1_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_2_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_3_apk.apk", zip file "/data/app/com.example.sprite.half_lifetimer-yUem3V7qOCQOMoGaFSaKEQ==/split_lib_slice_4_apk.apk", zip file "/data/app/com.example.sprite.half_
    109.         at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:93)
    110.         at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
    111.         at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
    112.         at void android.support.v4.view.ViewCompat.setOnApplyWindowInsetsListener(android.view.View, android.support.v4.view.OnApplyWindowInsetsListener) (ViewCompat.java:2203)
    113.         at android.view.ViewGroup android.support.v7.app.AppCompatDelegateImpl.createSubDecor() (AppCompatDelegateImpl.java:637)
    114.         at void android.support.v7.app.AppCompatDelegateImpl.ensureSubDecor() (AppCompatDelegateImpl.java:518)
    115.         at void android.support.v7.app.AppCompatDelegateImpl.setContentView(int) (AppCompatDelegateImpl.java:466)
    116.         at void android.support.v7.app.AppCompatActivity.setContentView(int) (AppCompatActivity.java:140)
    117.         at void com.example.sprite.half_lifetimer.SubData.onCreate(android.os.Bundle) (SubData.java:41)
    118.         at void android.app.Activity.performCreate(android.os.Bundle) (Activity.java:6982)
    119.         at void android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle) (Instrumentation.java:1214)
    120.         at android.app.Activity android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) (ActivityThread.java:2811)
    121.         at void android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:2933)
    122.         at void android.app.ActivityThread.-wrap11(android.app.ActivityThread, android.app.ActivityThread$ActivityClientRecord, android.content.Intent, java.lang.String) (ActivityThread.java:-1)
    123.         at void android.app.ActivityThread$H.handleMessage(android.os.Message) (ActivityThread.java:1612)
    124.         at void android.os.Handler.dispatchMessage(android.os.Message) (Handler.java:105)
    125. I/zygote64:     at void android.os.Looper.loop() (Looper.java:164)
    126.         at void android.app.ActivityThread.main(java.lang.String[]) (ActivityThread.java:6710)
    127.         at java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[]) (Method.java:-2)
    128.         at void com.android.internal.os.Zygote$MethodAndArgsCaller.run() (Zygote.java:240)
    129.         at void com.android.internal.os.ZygoteInit.main(java.lang.String[]) (ZygoteInit.java:770)
    130. D/loadSubstance: Initializing database
    131. I/SQLiteOpenHelper: Upgrade halflife-db
    132. D/AndroidRuntime: Shutting down VM
    133. E/AndroidRuntime: FATAL EXCEPTION: main
    134.     Process: com.example.sprite.half_lifetimer, PID: 22703
    135.     java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.sprite.half_lifetimer/com.example.sprite.half_lifetimer.SubData}: java.lang.IllegalStateException: Migration didn't properly handle UsualSuspect(com.example.sprite.half_lifetimer.UsualSuspect).
    136.      Expected:
    137.     TableInfo{name='UsualSuspect', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, notes=Column{name='notes', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    138.      Found:
    139.     TableInfo{name='UsualSuspect', columns={dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, notes=Column{name='notes', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, name=Column{name='name', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    140.         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2858)
    141.         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2933)
    142.         at android.app.ActivityThread.-wrap11(Unknown Source:0)
    143.         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1612)
    144.         at android.os.Handler.dispatchMessage(Handler.java:105)
    145.         at android.os.Looper.loop(Looper.java:164)
    146.         at android.app.ActivityThread.main(ActivityThread.java:6710)
    147.         at java.lang.reflect.Method.invoke(Native Method)
    148.         at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    149.         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:770)
    150.      Caused by: java.lang.IllegalStateException: Migration didn't properly handle UsualSuspect(com.example.sprite.half_lifetimer.UsualSuspect).
    151.      Expected:
    152.     TableInfo{name='UsualSuspect', columns={name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1}, notes=Column{name='notes', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    153.      Found:
    154.     TableInfo{name='UsualSuspect', columns={dosage=Column{name='dosage', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, notes=Column{name='notes', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, name=Column{name='name', type='VARCHAR', affinity='2', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, sid=Column{name='sid', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}}, foreignKeys=[], indices=[]}
    155.         at com.example.sprite.half_lifetimer.AppDatabase_Impl$1.validateMigration(AppDatabase_Impl.java:114)
    156.         at android.arch.persistence.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:87)
    157.         at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:133)
    158.         at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:302)
    159.         at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:194)
    160.         at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
    161. E/AndroidRuntime:     at android.arch.persistence.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
    162.         at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:233)
    163.         at com.example.sprite.half_lifetimer.SubstanceDao_AppDatabase_Impl.getAll(SubstanceDao_AppDatabase_Impl.java:147)
    164.         at com.example.sprite.half_lifetimer.Permanence.loadSubstances(Permanence.java:39)
    165.         at com.example.sprite.half_lifetimer.SubData.onCreate(SubData.java:82)
    166.         at android.app.Activity.performCreate(Activity.java:6982)
    167.         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
    168.         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2811)
    169.             ... 9 more
    170.  
     
  5. Deleted User

    Deleted User Guest

    The '9 more' are irrelevant and won't provide any more useful information. Stack traces read from top to bottom, and the most relevant line is at the top, just before the exception message.
    In particular you want to be looking at this line

    Code (Text):
    1.  
    2. at com.example.sprite.half_lifetimer.AppDatabase_Impl$1.validateMigration(AppDatabase_Impl.java:114)
    3.  
     
    GameTheory likes this.
  6. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Understood, thank you for clarification.
     
  7. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Other than that, however, I must admit that, after looking at AppDatabase_Impl.java (line 114 and the associated block), I'm still utterly clueless. If there's anything of relevance there that I'm missing, I'd sure appreciate if anybody could point it out to me so that I know what to look for in the future.

    Code (Text):
    1.  
    2. package com.example.sprite.half_lifetimer;
    3.  
    4. import android.arch.persistence.db.SupportSQLiteDatabase;
    5. import android.arch.persistence.db.SupportSQLiteOpenHelper;
    6. import android.arch.persistence.db.SupportSQLiteOpenHelper.Callback;
    7. import android.arch.persistence.db.SupportSQLiteOpenHelper.Configuration;
    8. import android.arch.persistence.room.DatabaseConfiguration;
    9. import android.arch.persistence.room.InvalidationTracker;
    10. import android.arch.persistence.room.RoomOpenHelper;
    11. import android.arch.persistence.room.RoomOpenHelper.Delegate;
    12. import android.arch.persistence.room.util.TableInfo;
    13. import android.arch.persistence.room.util.TableInfo.Column;
    14. import android.arch.persistence.room.util.TableInfo.ForeignKey;
    15. import android.arch.persistence.room.util.TableInfo.Index;
    16. import java.lang.IllegalStateException;
    17. import java.lang.Override;
    18. import java.lang.String;
    19. import java.lang.SuppressWarnings;
    20. import java.util.HashMap;
    21. import java.util.HashSet;
    22.  
    23. @SuppressWarnings("unchecked")
    24. public class AppDatabase_Impl extends AppDatabase {
    25.   private volatile SubstanceDao _substanceDao;
    26.  
    27.   private volatile UsageDao _usageDao;
    28.  
    29.   private volatile UsualSuspectDao _usualSuspectDao;
    30.  
    31.   @Override
    32.   protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
    33.     final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(4) {
    34.       @Override
    35.       public void createAllTables(SupportSQLiteDatabase _db) {
    36.         _db.execSQL("CREATE TABLE IF NOT EXISTS `Substance` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `units` INTEGER, `cname` TEXT, `sname` TEXT, `halflife` INTEGER NOT NULL, `detectable_halflife` INTEGER NOT NULL, `lipid_soluble` INTEGER NOT NULL)");
    37.         _db.execSQL("CREATE TABLE IF NOT EXISTS `Usage` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `sub_id` INTEGER NOT NULL, `dosage` REAL NOT NULL, `timestamp` INTEGER, `notes` TEXT)");
    38.         _db.execSQL("CREATE TABLE IF NOT EXISTS `UsualSuspect` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `sid` INTEGER NOT NULL, `dosage` REAL NOT NULL, `notes` TEXT)");
    39.         _db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
    40.         _db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"bbc676cc6d4f19002e4df137eff5f3f8\")");
    41.       }
    42.  
    43.       @Override
    44.       public void dropAllTables(SupportSQLiteDatabase _db) {
    45.         _db.execSQL("DROP TABLE IF EXISTS `Substance`");
    46.         _db.execSQL("DROP TABLE IF EXISTS `Usage`");
    47.         _db.execSQL("DROP TABLE IF EXISTS `UsualSuspect`");
    48.       }
    49.  
    50.       @Override
    51.       protected void onCreate(SupportSQLiteDatabase _db) {
    52.         if (mCallbacks != null) {
    53.           for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
    54.             mCallbacks.get(_i).onCreate(_db);
    55.           }
    56.         }
    57.       }
    58.  
    59.       @Override
    60.       public void onOpen(SupportSQLiteDatabase _db) {
    61.         mDatabase = _db;
    62.         internalInitInvalidationTracker(_db);
    63.         if (mCallbacks != null) {
    64.           for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
    65.             mCallbacks.get(_i).onOpen(_db);
    66.           }
    67.         }
    68.       }
    69.  
    70.       @Override
    71.       protected void validateMigration(SupportSQLiteDatabase _db) {
    72.         final HashMap<String, TableInfo.Column> _columnsSubstance = new HashMap<String, TableInfo.Column>(7);
    73.         _columnsSubstance.put("id", new TableInfo.Column("id", "INTEGER", true, 1));
    74.         _columnsSubstance.put("units", new TableInfo.Column("units", "INTEGER", false, 0));
    75.         _columnsSubstance.put("cname", new TableInfo.Column("cname", "TEXT", false, 0));
    76.         _columnsSubstance.put("sname", new TableInfo.Column("sname", "TEXT", false, 0));
    77.         _columnsSubstance.put("halflife", new TableInfo.Column("halflife", "INTEGER", true, 0));
    78.         _columnsSubstance.put("detectable_halflife", new TableInfo.Column("detectable_halflife", "INTEGER", true, 0));
    79.         _columnsSubstance.put("lipid_soluble", new TableInfo.Column("lipid_soluble", "INTEGER", true, 0));
    80.         final HashSet<TableInfo.ForeignKey> _foreignKeysSubstance = new HashSet<TableInfo.ForeignKey>(0);
    81.         final HashSet<TableInfo.Index> _indicesSubstance = new HashSet<TableInfo.Index>(0);
    82.         final TableInfo _infoSubstance = new TableInfo("Substance", _columnsSubstance, _foreignKeysSubstance, _indicesSubstance);
    83.         final TableInfo _existingSubstance = TableInfo.read(_db, "Substance");
    84.         if (! _infoSubstance.equals(_existingSubstance)) {
    85.           throw new IllegalStateException("Migration didn't properly handle Substance(com.example.sprite.half_lifetimer.Substance).\n"
    86.                   + " Expected:\n" + _infoSubstance + "\n"
    87.                   + " Found:\n" + _existingSubstance);
    88.         }
    89.         final HashMap<String, TableInfo.Column> _columnsUsage = new HashMap<String, TableInfo.Column>(5);
    90.         _columnsUsage.put("id", new TableInfo.Column("id", "INTEGER", true, 1));
    91.         _columnsUsage.put("sub_id", new TableInfo.Column("sub_id", "INTEGER", true, 0));
    92.         _columnsUsage.put("dosage", new TableInfo.Column("dosage", "REAL", true, 0));
    93.         _columnsUsage.put("timestamp", new TableInfo.Column("timestamp", "INTEGER", false, 0));
    94.         _columnsUsage.put("notes", new TableInfo.Column("notes", "TEXT", false, 0));
    95.         final HashSet<TableInfo.ForeignKey> _foreignKeysUsage = new HashSet<TableInfo.ForeignKey>(0);
    96.         final HashSet<TableInfo.Index> _indicesUsage = new HashSet<TableInfo.Index>(0);
    97.         final TableInfo _infoUsage = new TableInfo("Usage", _columnsUsage, _foreignKeysUsage, _indicesUsage);
    98.         final TableInfo _existingUsage = TableInfo.read(_db, "Usage");
    99.         if (! _infoUsage.equals(_existingUsage)) {
    100.           throw new IllegalStateException("Migration didn't properly handle Usage(com.example.sprite.half_lifetimer.Usage).\n"
    101.                   + " Expected:\n" + _infoUsage + "\n"
    102.                   + " Found:\n" + _existingUsage);
    103.         }
    104.         final HashMap<String, TableInfo.Column> _columnsUsualSuspect = new HashMap<String, TableInfo.Column>(5);
    105.         _columnsUsualSuspect.put("id", new TableInfo.Column("id", "INTEGER", true, 1));
    106.         _columnsUsualSuspect.put("name", new TableInfo.Column("name", "TEXT", false, 0));
    107.         _columnsUsualSuspect.put("sid", new TableInfo.Column("sid", "INTEGER", true, 0));
    108.         _columnsUsualSuspect.put("dosage", new TableInfo.Column("dosage", "REAL", true, 0));
    109.         _columnsUsualSuspect.put("notes", new TableInfo.Column("notes", "TEXT", false, 0));
    110.         final HashSet<TableInfo.ForeignKey> _foreignKeysUsualSuspect = new HashSet<TableInfo.ForeignKey>(0);
    111.         final HashSet<TableInfo.Index> _indicesUsualSuspect = new HashSet<TableInfo.Index>(0);
    112.         final TableInfo _infoUsualSuspect = new TableInfo("UsualSuspect", _columnsUsualSuspect, _foreignKeysUsualSuspect, _indicesUsualSuspect);
    113.         final TableInfo _existingUsualSuspect = TableInfo.read(_db, "UsualSuspect");
    114.         if (! _infoUsualSuspect.equals(_existingUsualSuspect)) {
    115.           throw new IllegalStateException("Migration didn't properly handle UsualSuspect(com.example.sprite.half_lifetimer.UsualSuspect).\n"
    116.                   + " Expected:\n" + _infoUsualSuspect + "\n"
    117.                   + " Found:\n" + _existingUsualSuspect);
    118.         }
    119.       }
    120.     }, "bbc676cc6d4f19002e4df137eff5f3f8", "734a65b5a98466c1af75b68af768a084");
    121.     final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)
    122.         .name(configuration.name)
    123.         .callback(_openCallback)
    124.         .build();
    125.     final SupportSQLiteOpenHelper _helper = configuration.sqliteOpenHelperFactory.create(_sqliteConfig);
    126.     return _helper;
    127.   }
    128.  
    129.   @Override
    130.   protected InvalidationTracker createInvalidationTracker() {
    131.     return new InvalidationTracker(this, "Substance","Usage","UsualSuspect");
    132.   }
    133.  
    134.   @Override
    135.   public void clearAllTables() {
    136.     super.assertNotMainThread();
    137.     final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
    138.     try {
    139.       super.beginTransaction();
    140.       _db.execSQL("DELETE FROM `Substance`");
    141.       _db.execSQL("DELETE FROM `Usage`");
    142.       _db.execSQL("DELETE FROM `UsualSuspect`");
    143.       super.setTransactionSuccessful();
    144.     } finally {
    145.       super.endTransaction();
    146.       _db.query("PRAGMA wal_checkpoint(FULL)").close();
    147.       if (!_db.inTransaction()) {
    148.         _db.execSQL("VACUUM");
    149.       }
    150.     }
    151.   }
    152.  
    153.   @Override
    154.   public SubstanceDao getSubstanceDao() {
    155.     if (_substanceDao != null) {
    156.       return _substanceDao;
    157.     } else {
    158.       synchronized(this) {
    159.         if(_substanceDao == null) {
    160.           _substanceDao = new SubstanceDao_AppDatabase_Impl(this);
    161.         }
    162.         return _substanceDao;
    163.       }
    164.     }
    165.   }
    166.  
    167.   @Override
    168.   public UsageDao getUsageDao() {
    169.     if (_usageDao != null) {
    170.       return _usageDao;
    171.     } else {
    172.       synchronized(this) {
    173.         if(_usageDao == null) {
    174.           _usageDao = new UsageDao_AppDatabase_Impl(this);
    175.         }
    176.         return _usageDao;
    177.       }
    178.     }
    179.   }
    180.  
    181.   @Override
    182.   public UsualSuspectDao getUsualSuspectDao() {
    183.     if (_usualSuspectDao != null) {
    184.       return _usualSuspectDao;
    185.     } else {
    186.       synchronized(this) {
    187.         if(_usualSuspectDao == null) {
    188.           _usualSuspectDao = new UsualSuspectDao_AppDatabase_Impl(this);
    189.         }
    190.         return _usualSuspectDao;
    191.       }
    192.     }
    193.   }
    194. }
    195.  
     
  8. Deleted User

    Deleted User Guest

    Your HashMap equality test returns false, because they have different entries.
    This line

    Code (Text):
    1.  
    2. _columnsUsualSuspect.put("name", new TableInfo.Column("name", "TEXT", false, 0));
    3.  
    Differs from the column definition in your existing database table, which has a value of 'true' for the notNull attribute.
    If you had written instead

    Code (Text):
    1.  
    2. _columnsUsualSuspect.put("name", new TableInfo.Column("name", "TEXT", true, 0));
    3.  
    then assuming there aren't any other discrepancies, then the equality test would return true, and you wouldn't see that error message.

    So the code is behaving exactly as you have written it. My question to you is, what did you expect to happen?
     
    GameTheory likes this.
  9. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Well, actually AppDatabase_Impl.java is generated code, so I didn't write it. That's one of the reasons that I'm not so clear on what it does. I understand what you're saying about the 2 different lines of code, but I'm pretty sure that it was generated from the following (in AppDatabase.java):

    Code (Text):
    1.  
    2. static final Migration MIGRATION_3_4 = new Migration(3, 4) {
    3.     @Override
    4.     public void migrate(SupportSQLiteDatabase database) {
    5.         database.execSQL("CREATE TABLE IF NOT EXISTS `UsualSuspect` (`id` INTEGER, `name` " +
    6.                 "VARCHAR NOT NULL, `sid` " + "INTEGER NOT NULL, `dosage` REAL NOT NULL, " +
    7.                 "`notes` VARCHAR NOT NULL, PRIMARY KEY (`id`))");
    8.     }
    9. };
    10.  
    At least I think so, being as it has the filename of code that I did write, which is vaguely similar to AppDatabase_Impl.java.

    The other possibility is that it was generated from UsualSuspects.java, which I'm not going to paste here again for brevity's sake, but is available in the original post. However, there's nothing in that particular class/table definition that has to due with 'null=false', as there is in the above snippet, so I doubt that that has anything to do with it.

    I may be missing something obvious here, but I'm pretty sure that every column in the table defined above does, indeed, have NOT NULL specified for it. So the question at this point would be why AppDatabase_Impl.java is being generated with things the way that they are in there right now, right?

    I'm confused as all hell by how this is playing out, and do apologize sincerely if I'm missing something or being (not deliberately, at least) obtuse about what's going on here.

    Thanks for the assistance.
     
  10. Deleted User

    Deleted User Guest

    Ah ok, another piece falls into place :)
    I'm kind of flying in the dark here, as I've not been through the process of upgrading a Room database. But that auto-generated code doesn't make a lot of sense to me. Why produce all that column checking code, if the intention is just to create a table if it doesn't exist?
    Could you modify the generated code to take out the column checking stuff? In fact, how is that code generated in the first place?
     
  11. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    It doesn't make sense to me, either. I wish to the higher powers that be that I could find anything more than just the original dox for Room when I'm searching around... There's really a lack of good resources on this ORM, unless they're all just hiding in a crevasse that I haven't found yet.

    The auto-generated code, after I click the generated code link in the stack trace in order to view it, gives me a warning that it shouldn't be modified, but I guess I might as well give it a shot. I can always do a git reset --hard afterwards, if it screws things up as badly as AS seems to think that it might. If it's generated fresh every time, though, it's not going to do much good if I have to do that every single time that I build the app from here on out. :|

    I'm starting to think that maybe I should just focus more on a JSON dump & import capability in my app, and fall back to destructive migration again. That'd really limit me to making sure that my database has pretty much every scenario taken into account before I distribute it, though, and if I do end up running into a scenario that requires a database update, any users will have no choice except to wipe their database or do a nasty JSON dump & re-import afterwards. :p
     
  12. Deleted User

    Deleted User Guest

    Do you have a link to a git repo that I can clone? If I get some time this weekend, I could try it myself and see what happens.
     
    GameTheory likes this.
  13. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Sure! The repo is here, let me know if you have any problems accessing it.

    I'm a little self-conscious about it, so just let me say before you delve into anything that I was picking up Java again, after a very long time, while writing this project, and definitely learning Android Studio as I went. So there are some weird bits in the code, such as a spot where I didn't know how to add things to a layout programmatically yet, so I had added them via the layout editor, then removed everything from the view, and then added them again, etc... If you're just looking at this particular issue, things should be mostly clean and tidy, but I just wanted to let you know, should you happen to stumble onto the earlier bits of code in this project. Don't hold it too much against me, I was learning through trial & error. :)

    Also, I really wanted to say thank you again about taking at look at this, and all. It's pretty awesome that you're actually willing to take a look at the repo and the codebase itself if you've got a chance, and I really appreciate it.
     
    GameTheory likes this.
  14. Deleted User

    Deleted User Guest

    First problem is the activity_sub_data.xml fails to build because this drawable resource is missing

    Code (Text):
    1.  
    2. android:src="@drawable/plus_medical_blue"
    3.  
     
    GameTheory likes this.
  15. Deleted User

    Deleted User Guest

    Ok so after commenting that out, and uncommenting the migration code in the AppDatabase class, the app runs successfully for me.
    How do you get the above problems?
     
    GameTheory likes this.
  16. Deleted User

    Deleted User Guest

    Repo appears to be missing the troublesome database table "UsualSuspect".
     
    GameTheory likes this.
  17. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Oh, my bad. I should've specified that those changes are in a branch aside from master. I'm using the git flow methodology, so they currently reside in feature/add-usual-suspects. Also, it should be triggering the migration, if you previously built from master, but if you build straight from feature/add-usual-suspects without having a previously built database from master or develop, you may not see the error. Not sure because I've not been through that scenario yet.

    Going to be traveling for a bit today, so my apologies if my replies take a bit for the next while...
     
  18. Deleted User

    Deleted User Guest

    Well I can confirm that this is indeed frustrating as hell :mad:
    I feel though that I've wandered into the story part way through. You're already on version 4 of the DB. What was the deal with versions 1..3?

    And another thing is that your migration code is attempting to create a table, which already exists in the DB. Why? Normally a table upgrade would typically be adding/removing, or modifying table columns in some way.

    And also I just don't get this bit of autogen'd code

    Code (Text):
    1.  
    2. _columnsUsualSuspect.put("id", new TableInfo.Column("id", "INTEGER", true, 1));
    3. _columnsUsualSuspect.put("name", new TableInfo.Column("name", "TEXT", false, 0));
    4. _columnsUsualSuspect.put("sid", new TableInfo.Column("sid", "INTEGER", true, 0));
    5. _columnsUsualSuspect.put("dosage", new TableInfo.Column("dosage", "REAL", true, 0));
    6. _columnsUsualSuspect.put("notes", new TableInfo.Column("notes", "TEXT", false, 0));
    7.  
    Those true/false values are the NULLABLE parameters for the columns. Where are these values coming from because they are not specified in your DB Entity class (UsualSuspect).
    And they certainly don't agree with what's currently defined on the existing UsualSuspect table.
     
    GameTheory likes this.
  19. Deleted User

    Deleted User Guest

  20. Deleted User

    Deleted User Guest

    I cracked it!!
    In your migrate() method, the correct table creation script is as follows:

    Code (Text):
    1.  
    2. database.execSQL("CREATE TABLE IF NOT EXISTS `UsualSuspect` " +
    3.         "(`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
    4.         "`name` TEXT, `sid` INTEGER NOT NULL, `dosage` REAL NOT NULL, " +
    5.         "`notes` TEXT)");
    6.  
    I simply copied this statement from the AppDatabase_Impl class at line 37.
     
    GameTheory and Damon Getsman like this.
  21. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Okay, I may be mistaken in parts of this, but here is how I understand it... When I did migrations to version 2 and migration 3, my migrations failed miserably. I didn't have enough in the database at that point to warrant suffering through the debaucle that we're currently engaged in right now, so I added the line in AppDatabase.java (namely `.fallbackToDestructiveMigration()`), which allowed a destructive migration. I commented out the migrations from 1-2, and 2-3, because the destructive migration made those moot. Now that you mention it, though, maybe the missing migrations are, for some reason, causing migration 3-4 to fail... Being as I'm successfully at version 3, I wouldn't expect this to be the case, but things are hardly working as I expect them to at this point, so I'll give it a shot...

    Okay, restoring those migrations still results in the exact same error, so I think that my beliefs as far as the methodology behind how this is working still stand. I did, however, just push a commit with those migrations restored (I'd deleted them despite them being commented out previously for some foolish reason). So if you pull a new version of the features/add-usual-suspects branch, you'll be able to see all of the database migration code, at least.

    Okay I'm not sure about that autogen code. Not sure what to tell you there.

    However, regarding the NULLABLE parameters, I did specify those manually in AppDatabase.java's migration code.

    I just got back from my trip, and I'm pretty exhausted, so I don't really have anything else to add to this at this point. I will, however, take another round of looking and debugging things in the morning after I've had some sleep and see if I have any other insights to add. Sorry I don't really have anything else at this point.
     
  22. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Oh, I also forgot to mention, I took a look at the database, myself, and in my database UsualSuspect hasn't been created at all. I suspect the different between our two databases may exist because there are no records in your existing database prior to attempt at creation or migration to version 4, or you jumped straight to creating a database at version 4 without 3 or prior being created at all. Not sure on that, though. :oops:
     
  23. Deleted User

    Deleted User Guest

    I posted a solution to the v3 - v4 migration issue in post #19. Your SQL code wasn't right. If you copy the table creation SQL from AppDatabase_Impl, (as per my given code) it works.
     
    GameTheory and Damon Getsman like this.
  24. Damon Getsman

    Damon Getsman Newbie
    Thread Starter

    Well holy crap. Thank you so very much, LV426. I would've never caught that on my own. I wish I could buy you a beer or something!
     
  25. Deleted User

    Deleted User Guest

    Just deposit a couple of bottles of this in the staff fridge please :)

    mead.jpg
     
    GameTheory and Damon Getsman like this.
  26. GameTheory

    GameTheory Android Expert

    Dang LV, it's amazing how you troubleshooted through this and cracked the code. Such badassery! Very impressive!

    I hereby dub thee, "Java Jedi". :cool: :D
     
    Deleted User and Damon Getsman like this.
Loading...

Share This Page

Loading...