Clearly this question has been asked before, but despite looking at several responses, I'm still a bit unsure. The docs for the onUpgrade() method didn't really help either.
Does onUpgrade() get run for each version increment (i.e., from db_v1 to db_v3 onUpgrade() is run once for 1->2, then again for 2->3), or is it just run once (i.e., from db_v1 to db_v3 onUpgrade() is run once for 1->3);
My assumption is that it only is called once. In which case, would something like this work OK?
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 0:
migrateDatabaseToVersion_1(db);
migrateDatabaseToVersion_2(db);
migrateDatabaseToVersion_3(db);
break;
case 1:
migrateDatabaseToVersion_2(db);
migrateDatabaseToVersion_3(db);
break;
case 2:
migrateDatabaseToVersion_3(db);
break;
default:
Log.d(LOG, "no database migrations necessary");
break;
}
}
I saw a response here that kind of suggest something similar, but using if statements instead of switch. Any help is much appreciated. Thank you in advance.
The documentation doesn't say this explicitly, but it wouldn't make sense to give both the old and new version numbers as parameters if it would be called for each increment.
Note: it is preferrable to use a series of if statements instead of a switch: as long as the old version is smaller than the version for the n-th step, upgrade that step.
Not only does this avoid duplications, but also prevents you from forgetting a break ...
Related
For SQLiteOpenHelper, if I add a new table inside onCreate do I have to do anything inside onUpgrade? I am adding a completely new table. I believe I have to change the version number but that onUpgrade should remain empty. Is that correct?
If you want existing installs of the app to add this new table, then yes, you must increase the version and provide a suitable onUpgrade() implementation, as well as adding the table in onCreate() (which you stated you have already done).
An empty onUpgrade() implementation is not sufficient; it has to actually do something. Some people drop all tables and just call onCreate() directly, but this obviously doesn't work well if you are trying to keep existing data. I usually use the fall-through switch idiom, so that if a user is more than one version behind (e.g. you publish a version 3 and a user is still on version 1) they will go through all the necessary upgrades sequentially:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL("CREATE TABLE " + ...);
// no break statement, so case 2 will execute after this.
case 2:
// more execSQL(), etc
}
}
onCreate() will not be called if a user already has installed your app previously. So you need to create the new table in onUpgrade(), too. Be sure to increase the version number of your database.
I suggest putting the code to create the table in a helper method so that you can call it from both callback methods. This will reduce the chance of an error in case you need to change the code to create the table.
onUpgrade will only be called if you increase the version number.
To implement it you must recreate the tables with any changes you have made and copy over any existing data. There are many tutorials on this topic.
It is not necessary to implement if you are still learning, but if you don't and you make any changes to your schema you'll need to uninstall the app from the device or the changes won't be applied.
This is a trivial question, but I am afraid to put in production wrong code and that testing in devices/emulator could lead to cache problems that do not mirror the reality.
My assumptions:
As well documented on SO, I need to add a column to my DB, I decided to use ALTER table ADD column
in onUpgrade(), and to change the version in the constructor of the DB from 1 to 2, so that the constructor will recognize that is running the new version and the onUpgrade() function should be triggered.
My 2 problems:
1) MOST IMPORTANT. Let's assume old users will upgrade successfully the db, but what happens with new users that still have to create even the first row of the DB, will they be directed to OnCreate() and not onUpgrade() because version is 2, or to on OnCreate() and then onUpgrade(), or almost impossible directly in OnUpgrade() skipping for some API reason even onCreate()?
In other terms do I need to update the new column changing the old onCreate() comprehending the new added column?
2) in onUpgrade() after
ALTER <table> ADD <column>
logically do I have to CREATE a new table right? Should I call onCreate() that as an updated Table( ex. instead of the original 4 column, now has 5 columns)?
When getWritableDatabase() is called, it checks the database file. If it does not exist, onCreate is called. If it does exist, but has a wrong version, onUpgrade is called.
So onCreate is responsible for creating the database schema of the current version, while onUpgrade is responsible for changing some existing database to have the schema of the current version.
You could share code between onCreate and onUpgrade, but calling that code is your own responsibility; the framework will not check the version again after the onXxx callback has returned.
I want to know if it is possible to add a table to my remote database after the app has been running on my device for a couple of weeks, and still work?
For instance, if I'm using a Android device and have a simple game with 3 levels using SQLite db. Now I want to add a 4th level to the game, without losing progress on the other 3 levels or having to re install the app to accommodate for db changes?
In simple words YES it's possible. You can change your database design with out losing any data. You can achieve by overriding the 'onUpgrade' method in your database class which extends SQLiteOpenHelper.
You need to change the database version number when you update your app. If the database version number is greater than the previous one then onUpgrade method get called.
#Override
public void onUpgrade(SQLiteDatabase db, int newVersionNumber, int oldVersionNumber) {
// Do your Changes here. You can Alter table, Drop column etc
}
Remote Database - Its not linked with app. So you can change what ever you want. It won't affect your app. But you need to handle it efficiently.
Hope it helps.
Yes. it is possible, you can upgrade it.
You must set old and new database version.
public void onUpgrade(SQLiteDatabase db, int newVersionNumber, int
oldVersionNumber)
i am currently stuck in a problem with the asyncSession. I tried to not just make a list, i wanted to call asyncSession.queryList().
I don't have the log-file rightnow, but it basically said that the query wasn't build in the currentThreat. (I am building it one line above)
So i tried to add .forCurrentThread(), but i got the same error.
Is this feature basically working?
Otherwise i will bring some more information tomorrow.
I ran into the same problem and came to the conclusion this was a bug. I ended up changing the method executeOperation() in AsyncOperationExecutor.java:
case QueryList:
operation.result = ((Query) operation.parameter).forCurrentThread().list();
break;
case QueryUnique:
operation.result = ((Query) operation.parameter).forCurrentThread().unique();
break;
Adding in the call to forCurrentThread() changes the owning thread of the Query to the thread of the ExecutorService. This made it work for me, I wonder if there is a better solution though.
Is there any documentation on how to best deal with database upgrades in android?
I am developing an application and have been testing it on my own telephone. All works fine, over the past few deploys I had to add some columns to my table and due to upgrade statements that are executed if the old database version is lesser then a certain database version.
However when I try to run the application on another phone, that gives errors due to the fact that there is no previous version and thus the column isn't added.
Is there any best practice or documentation on how to handle database upgrading and versioning? I tried googling around for specific questions, but much good didn't come out of that.
Here's the relevant code I am using at the moment:
private static final int DATABASE_VERSION = 11;
private static class LocalLoginDatabaseHelper extends SQLiteOpenHelper {
LocalLoginDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG,DATABASE_CREATE);
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion < 11) {
Log.d(TAG + "Upgrade",DATABASE_ALTER);
db.execSQL(DATABASE_ALTER);
}
}
}
Thanks
Is there any documentation on how to best deal with database upgrades in android?
Use SQLiteOpenHelper, which will give you control when a schema change is detected, so you can upgrade the database.
UPDATE
However when I try to run the application on another phone, that gives errors due to the fact that there is no previous version and thus the column isn't added.
Your DATABASE_CREATE needs to have the column as well. For a new install (or after the user does Clear Data on your app), there is no existing database, and so onCreate(), not onUpgrade(), is called.
Shameless Plug: I know you have this issue resolved but I am working on an open source set of DSL's that makes it easy to create SqliteOpenHelper/ContentProvider/Contract API and manages upgrades through migrations http://robotoworks.com/mechanoid-plugin/mechanoid-db
Its still very early days and I am busy writing docs however its already useful to anyone working with sqlite in Android and the more people using it will make it better :)