ActiveAndroid
ActiveAndroid copied to clipboard
Migration script not running
Hi,
tl;dr What's the best way to check if a script is really running?
before adopting ActiveAndroid in our project I wanted to test the schema migration feature.
I followed the wiki instructions: https://github.com/pardom/ActiveAndroid/wiki/Schema-migrations and tried to add a column to a pre-existing db table but that's not working.
My inital Model class
@Table(name = "Person")
public class Person extends Model {
@Column
private String name;
}
All fine.
Then I added a new field called age:
@Table(name = "Person")
public class Person extends Model {
@Column
private String name;
@Column
private int age;
}
and changed the manifest flag + created the required assets/migrations/2.sql script
<meta-data android:name="AA_DB_VERSION" android:value="2" />
ALTER TABLE Person ADD COLUMN age INTEGER;
Still getting same error on new run
06-06 14:30:48.606: E/SQLiteLog(19359): (1) table Person has no column named age
Any clues?
What's the best way to check if the script is really running?
Thanks! Guido.
Additionally I just noticed that even for new classes/model tables are not created (and according to wiki ActiveAndroid should do this automatically).
My device is running Android 4.4 - is this OS version supported?
I have the same problem. Please help.
I have found solution. This is proper location of migration file: {APP_NAME}/app/src/main/assets/migrations/2.sql
Thank YOU @TomaszZGor that really needs to be documented! Seeing as assets doesn't exist in newer android studio projects.
@tayeke You welcome :)
I'm using eclipse and I'm not able to get the script 2.sql to run. I put it in {APP_NAME}/assets/migrations and changed AA_DB_VERSION to version 2 but the script doesn't get called. I really need this to work, currently because I have no alternatives, if I get an exception stating that the column doesn't exist, I run:
ActiveAndroid.execSQL("ALTER TABLE <TableName> ADD COLUMN <NewColumn> INTEGER;");
I can't debug ActiveAndroid because I can't run it in eclipse. Any ideas?
@shahalh please see my post above. You should save your sql file to: {APP_NAME}/app/src/main/assets/migrations/2.sql
@TomaszZGor from what I understand this is not correct in eclipse IDE. I have tried creating the path but it still didn't work. What you wrote is for Android Studio. Thanks,
Make sure you implement ActiveAndroid.initialize(this);
You can do this by having your main Application class extend com.activeandroid.app.Application. Or if you have a custom Application class implement ActiveAndroid.initialize(this); in onCreate()
I have tested with ActiveAndroid.initialize(this); and it started working, but then I removed it and only extended and it also worked, which led me to a conclusion that I was not checking this issue correctly. I'm using Questoid SQLite manger plugin for eclipse to examine the DB structure and data. But it seems that it has some sort of cache which doesn't always refresh, so after the migration scripts worked the DB viewer didn't show them as updated. When I restarted eclipse, I could see the migration scripts working, problem solved.
Im having the same problem when saving user table, I have added columns, even uninstalling and clearing data, and removing db using adb rm -rf database.db. not working..
I dont really understand, I thought Active Android recreates database and tables, even when unisntalling and clearing data. It doesnt work. Is there any work around ?
In my custom Application Class, I'm actually using ActiveAndroid's configuration builder and setting the DB Version as like configurationBuilder.setDatabaseVersion(2);
and in my AndroidManifest.xml also I have defined AA_DB_VERSION
metadata as 2.
My 2.sql
version location is also, APP_NAME/src/main/assets/migrations/2.sql
But initialising with configurationBuilder object, like, ActiveAndroid.initialize(configurationBuilder.create());
Still it's not working. Any idea ?
** UPDATE TO PREVIOUS COMMENT: ** Oh my god, I never expected this could be an issue. Really wondering how those awesome developers who developed ActiveAndroid missed this thing..
My 2.sql file had standard SQL comments like below,
/**
* My comments
*/
ALTER TABLE myTable ADD COLUMN MyNewColumn TEXT;
com.activeandroid.DatabaseHelper.java
simply executes the line one by one without knowing whether it is comment or not.
Dear developers, is that intentionally done so ??
@shahalh Yes. My answer is ok for Android Studio.
Folks, is there any difference in migration between cases with automatic and manual initialization?
In app with automatic initialization the migration works fine.
ActiveAndroid.initialize(dbConfiguration);
In app with manual initializatin the migration scripts do not run.
Configuration dbConfiguration =
new Configuration.Builder(this)
.setDatabaseName("ab.db")
.setDatabaseVersion(2)
.create();
In experiment I uninstall app, install and run it with version number 1, than set version to 2 and run again.
Is there any ideas?
This issue cannot be solved or what?
In your onCreate Application.class
ActiveAndroid.initialize(this);
DBHelper.createIfNeedColumn(YOUR_ORM_CLASS, COLUMN_KEY);
And DBHelper.class static class
public static boolean createIfNeedColumn(Class<? extends Model> type, String column) {
boolean isFound = false;
TableInfo tableInfo = new TableInfo(type);
Collection<Field> columns = tableInfo.getFields();
for (Field f : columns) {
if (column.equals(f.getName())) {
isFound = true;
break;
}
}
if (!isFound) {
ActiveAndroid.execSQL("ALTER TABLE " + tableInfo.getTableName() + " ADD COLUMN " + column + " TEXT;");
}
return isFound;
}
@artemkutukov solution worked for me but needs some changes tableInfo.getFields() returns field of your model that extended from actvieAndroid.Model not real database columns. For get columns of real database use this code: `public static boolean createIfNeedColumn(Class<? extends Model> type, String column) { boolean isFound = false; TableInfo tableInfo = new TableInfo(type);
Cursor cursor = ActiveAndroid.getDatabase().query(tableInfo.getTableName(),null,null,null,null,null,null);
String columnNames[] = cursor.getColumnNames();
for (String f : columnNames) {
if (column.equals(f)) {
isFound = true;
break;
}
}
if (!isFound) {
ActiveAndroid.execSQL("ALTER TABLE " + tableInfo.getTableName() + " ADD COLUMN " + column + " TEXT;");
}
return isFound;
}`
I was running into issues with this and realized that if you have run the application ONCE with the upgrade sql file in the wrong location, the database has already been "upgraded" and any subsequent attempts to get it working will be ignored (since the database version is already incremented). You can see if this is the case by lowering the database version back to the original value, you will get an error on startup saying it cannot be downgraded.
Bumping the version number up to 3 and renaming the sql file to 3.sql made it run correctly.
Not sure if this will be the case if something is wrong inside the sql file when its run as well, just thought it might be useful to someone while troubleshooting.