Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table missing column on actual device only #1345

Closed
CapnSpellcheck opened this issue Jun 23, 2017 · 5 comments
Closed

Table missing column on actual device only #1345

CapnSpellcheck opened this issue Jun 23, 2017 · 5 comments

Comments

@CapnSpellcheck
Copy link

CapnSpellcheck commented Jun 23, 2017

DBFlow Version: 4.0.0-beta-something
Issue Kind (Bug, Question, Feature): Question

Description: At some point I added 'profileID' column to a table. App works fine in emulator.

On real device, I keep getting this statement error. SQLite table doesn't seem to have 'profileID'. But why does this keep happening even after I delete app from device? DB file should be gone, then app will recreate DB when installed next? Here's the code in generated table code which shows that it should have the column if table creation is executed

  @Override
  public final String getCreationQuery() {
    return "CREATE TABLE IF NOT EXISTS `PhotoMedia`(`uri` TEXT NOT NULL,`dimensions` TEXT NOT NULL,`profileID` TEXT, PRIMARY KEY(`uri`)" + ");";
  }

E/AndroidRuntime: FATAL EXCEPTION: main
Process: letstwinkle.com.twinkle, PID: 1786
Theme: themes:{default=overlay:system, iconPack:system, fontPkg:system, com.android.systemui=overlay:system, com.android.systemui.navbar=overlay:system}
android.database.sqlite.SQLiteException: table PhotoMedia has no column named profileID (code 1): , while compiling: INSERT INTO PhotoMedia(uri,dimensions,profileID) VALUES (?,?,?)
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:994)
at com.raizlabs.android.dbflow.structure.database.AndroidDatabase.compileStatement(AndroidDatabase.java:59)
at com.raizlabs.android.dbflow.structure.ModelAdapter.getInsertStatement(ModelAdapter.java:64)
at com.raizlabs.android.dbflow.structure.ModelAdapter.getInsertStatement(ModelAdapter.java:51)
at com.raizlabs.android.dbflow.sql.saveable.ModelSaver.save(ModelSaver.java:31)
at com.raizlabs.android.dbflow.structure.ModelAdapter.save(ModelAdapter.java:102)
at com.raizlabs.android.dbflow.structure.BaseModel.save(BaseModel.java:62)
at letstwinkle.com.twinkle.model.UserProfile_Table.save(UserProfile_Table.java:779)
at letstwinkle.com.twinkle.model.UserProfile_Table.save(UserProfile_Table.java:35)
at letstwinkle.com.twinkle.model.UserProfile.save(UserProfile.kt:137)
at letstwinkle.com.twinkle.MyProfileActivity$handleOnCreate$userProfileResponseHandler$1.onResponse(MyProfileActivity.kt:64)
at letstwinkle.com.twinkle.MyProfileActivity$handleOnCreate$userProfileResponseHandler$1.onResponse(MyProfileActivity.kt:62)
at letstwinkle.com.twinkle.api.AbstractResponseAdapter.onResponse(APIClient.kt:631)
at letstwinkle.com.twinkle.api.AbstractResponseAdapter.onResponse(APIClient.kt:626)
at letstwinkle.com.twinkle.mock.ServiceMock$MockAsyncTask.onPostExecute(ServiceMock.kt:75)
at letstwinkle.com.twinkle.mock.ServiceMock$MockAsyncTask.onPostExecute(ServiceMock.kt:47)
at android.os.AsyncTask.finish(AsyncTask.java:651)
at android.os.AsyncTask.-wrap1(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5471)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

@trevjonez
Copy link
Contributor

is the device api 23 or newer where you can have the system auto backup app data? perhaps it is restoring from the backup an older schema db file where you didn't roll the schema version with the change?

@CapnSpellcheck
Copy link
Author

Not sure I follow you on "roll the schema version with the change", but a-ha, you do have a good point!
Is this what android:allowBackup in the manifest enables?

  1. Is there a way to nuke the data backup for the one app?
  2. Is android:allowBackup="true" generally safe with DBFlow?

@trevjonez
Copy link
Contributor

1: not sure. good one for google, but I would imagine there is a way.

2: allow backup safety entirely depends on your use case and contents. There are options you can exercise to configure what can and can't be backed up.

the schema version is the version you specify in your dbflow @Database annotation. Any change that affects the generated create table statements of existing tables needs to be accompanied with an incremented db version.

@CapnSpellcheck
Copy link
Author

Ah, okay - by 'roll' you meant increment basically. Yeah I know to do that, but I'm not sure how the device got stuck this time. I incremented the database version and deployed, but that didn't help. Anyway, thanks so much for replying, I can't imagine how much more time I could have wasted before figuring it out!

P.S. You can delete a single app's data (not the backup) from Settings by navigating to the app and clicking on 'Storage'. After that you might have to reinstall the app if you don't have the recovery enabled.

@CapnSpellcheck
Copy link
Author

Sorry for an additional question so much later.

I think root cause was, that there was no migration class defined. Is it currently required (since v4) to define the AlterTableMigration even just for new columns?

Does DBFlow plan to use mingration class for table alters long term? Such classes are wasteful, only running once, but adding to dex 64k limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants