pardom-zz / ActiveAndroid

Active record style SQLite persistence for Android
http://www.activeandroid.com
4.7k stars 1.03k forks source link

Migration script not running #233

Open gparente opened 10 years ago

gparente commented 10 years ago

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.

gparente commented 10 years ago

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?

TomaszZGor commented 10 years ago

I have the same problem. Please help.

TomaszZGor commented 10 years ago

I have found solution. This is proper location of migration file: {APP_NAME}/app/src/main/assets/migrations/2.sql

tayeke commented 10 years ago

Thank YOU @TomaszZGor that really needs to be documented! Seeing as assets doesn't exist in newer android studio projects.

TomaszZGor commented 10 years ago

@tayeke You welcome :)

shahalh commented 9 years ago

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?

TomaszAvaus commented 9 years ago

@shahalh please see my post above. You should save your sql file to: {APP_NAME}/app/src/main/assets/migrations/2.sql

shahalh commented 9 years ago

@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,

inspiredclick commented 9 years ago

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()

shahalh commented 9 years ago

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.

DavidMont commented 9 years ago

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 ?

sincerekamal commented 9 years ago

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 ?

sincerekamal commented 9 years ago

\ 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 ??

TomaszZGor commented 9 years ago

@shahalh Yes. My answer is ok for Android Studio.

tseglevskiy commented 9 years ago

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?

aemxn commented 8 years ago

This issue cannot be solved or what?

kutukoff commented 8 years ago

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;
    }
MohammadRezaei92 commented 7 years ago

@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;
}`
nili02 commented 7 years ago

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.