0

Updated: Bref: The answer of Kuffs is simple and correct. The answer of MikeT is a interesting approach.

Old version: I'm working on an android app. I need to know if there are a new sql version or not. If my db is up to date, I will trigger an async action. But how can I trigger my async action?

Currently, I have my own flag onNewVersion who is set to true in onUpgrade(). Then I do the check in onOpen(). Are there any other methods?

@override
onUpgrade(...) {
    onNewVersion = true;
    ...
}

@override
onOpen(...) {
    if (onNewVersion == FALSE)
        triggerAction();
}

Thanks.

Anh-Tuan Mai
  • 1,129
  • 19
  • 36
  • This my help you. https://stackoverflow.com/questions/8133597/android-upgrading-db-version-and-adding-new-table –  Sep 21 '17 at 08:56

3 Answers3

1

Check onUpgrade

Called when the database needs to be upgraded. The implementation should use this method to drop tables, add tables, or do anything else it needs to upgrade to the new schema version.

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion < 5) {
         db.execSQL("ALTER_TABLE_STATEMENT");
    }
    if (oldVersion < 6) {
         db.execSQL("ALTER_TABLE_STATEMENT2");
    }
}
IntelliJ Amiya
  • 74,896
  • 15
  • 165
  • 198
  • Maybe my question is not clear, since my database is up to date, `onUpgrade()` is not called. I want to trigger an action if my db is up to date. How can I do it better? – Anh-Tuan Mai Sep 21 '17 at 09:03
  • 1
    so, first , u have to check if DB is up to date? is it done? –  Sep 21 '17 at 09:11
  • 2
    beware of using `oldVersion == 5` etc. It is better to use `oldVersion < 5` in case a version is skipped. For example, if the user upgraded from V4 to V7, your intermediate Sql statements would not be called. – Kuffs Sep 21 '17 at 09:15
  • @Kuffs yes yes . – IntelliJ Amiya Sep 21 '17 at 09:19
1

You can set a flag inside your onUpgrade method of your SQLiteOpenHelper.

If the flag is not set by the time you get your reference to the OpenHelper then the database was already current and did not need updating.

Kuffs
  • 35,581
  • 10
  • 79
  • 92
0

Are there any other methods?

Yes, I personally use a sort of pseudo/wanted/desired schema and in short compare this against what actually exists columns, tables, indexes being created(tables indexes)/added(columns) as required.

As such I don't use versions and onUpgrade is empty.

for example these are the core methods in my SQLiteOpenhelper subclass :-

    @Override
    public void onCreate(SQLiteDatabase db) {
        usable = this.onExpand(db,false);
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldversion, int newversion) {
    }

    public boolean onExpand(SQLiteDatabase db, boolean buildandexpand) {
        boolean rv = true;
        if (db == null) {
            db = instance.getWritableDatabase();
        }
        // Is the Database definition valid to use?
        if (DBConstants.cardonsier.isDBDatabaseUsable()) {
            ArrayList<String> buildsql = DBConstants.cardonsier.generateDBBuildSQL(db);
            // Anything to build
            if (!buildsql.isEmpty()) {
                // YES so build the Database
                DBConstants.cardonsier.actionDBBuildSQL(db);
            }
            if (buildandexpand) {
                ArrayList<String> altersql = DBConstants.cardonsier.generateDBAlterSQL(db);
                if (!altersql.isEmpty()) {
                    DBConstants.cardonsier.actionDBAlterSQL(db);
                }
            }
        }
        else {
            rv = false;
        }
        return rv;
    }

DBConstants.cardoniser refers to the DBDatabase object defined as :-

    static final DBDatabase cardonsier = new DBDatabase(DATABASENAME,
            new ArrayList<>(Arrays.asList(
                    DBCardsTableConstants.CARDS,
                    DBUsertableConstants.USERS,
                    DBCardUserLinkTableConstants.CARDUSERLINKS,
                    DBPreftableConstants.PREFS,
                    DBPayeestableContants.PAYEES,
                    DBCategoriestableConstants.CATEGORIES,
                    DBCardCategoryLinkTableConstants.CARDCATEGORYLINKS,
                    DBCardPayeeLinkTableConstants.CARDPAYEELINKS,
                    DBTransactionsTableConstants.TRANSACTIONS,
                    DBCardTypesTableConstants.CARDTYPES
            ))
    );

i.e. the list of DBTable objects, they including DBColumn objects e.g :-

static final DBTable CARDS = new DBTable(CARDS_TABLE,
        new ArrayList<>(Arrays.asList(
                CARDID,
                CARDOWNER,
                CARDNAME,
                CARDTYPEREF,
                CARDNUMBER,
                CARDCVVCODE,
                CARDPIN,
                CARDNOTES,
                CARDEXPIRYDATE,
                CARDNAMEONCARD
        ))
);

Columns being defined like :-

static final DBColumn CARDID = new DBColumn(true);
static final DBColumn CARDOWNER = new DBColumn(
        CARDOWNER_COL,
        SQLINTEGER,
        false,
        "0"
);
static final DBColumn CARDNAME = new DBColumn(
        CARDNAME_COL,
        SQLTEXT,
        false,
        ""
);
static final DBColumn CARDTYPEREF = new DBColumn(
        CARDTYPEREF_COL,
        SQLINTEGER,
        false,
        "0"
);

Note! the first column CARDID, uses a shortcut constructor for standard _id columns.

To add a new column it's simply a matter of defining the DBColumn and including the DBColumn in the DBTable definition. The onExpand method will add the column via, in the case of a new column, the DBDatabase's actionDBAlterSQL method. New tables require the above plus the inclusion of the table in the DBDatabase definition and are applied by onExpand via the actionDBBuildSQL method.

onExpand is also called when the App(s) is started. However, with true being passed so that the actionDBAlterSQL method is called.

As an example adding :-

private static final String CARDCOLOUR_COL = "cardcolour";
..........
static final DBColumn CARDCOLOUR = new DBColumn(
        CARDCOLOUR_COL,
        SQLINTEGER,
        false,
        Long.toString(0x00_00_00_00_00L)
        // Flag, alpha, red, green, blue
        // Flag used to inidcate if colour has been set
);

and then adding CARDCOLOUR to the DBTable definition as per :-

static final DBTable CARDS = new DBTable(CARDS_TABLE,
        new ArrayList<>(Arrays.asList(
                CARDID,
                CARDOWNER,
                CARDNAME,
                CARDTYPEREF,
                CARDNUMBER,
                CARDCVVCODE,
                CARDPIN,
                CARDNOTES,
                CARDEXPIRYDATE,
                CARDNAMEONCARD,
                CARDCOLOUR     //<<<<<<<<<<
        ))
);

Results in (note logging exists when developing) :-

09-22 08:30:26.802 2713-2713/? D/DBEXPAND: Expanding Database Schema Usability=true
09-22 08:30:26.803 2713-2713/? D/DBEXPAND: Build SQL is as follows:-
09-22 08:30:26.803 2713-2713/? D/DBEXPAND: ALTERSQL is as folows:-
09-22 08:30:26.807 2713-2713/? D/DBEXPAND: ALterSQL Line=    ALTER TABLE cards ADD COLUMN cardcolour INTEGER  DEFAULT 0  ;

The resultant already populated table then looks like :-

enter image description here

Using ALTER TABLE with a DEFAULT value (4th parameter of DBColumn (1st is column name, 2nd Type, 3rd true to include in primary index)) populates the new column for existing rows.

MikeT
  • 51,415
  • 16
  • 49
  • 68
  • How do you check whether the db is up to date or not? – Anh-Tuan Mai Sep 21 '17 at 12:16
  • 1
    Basically by comparing the pseudo schema against the real database via inspection of sqlite_master and PRAGMA. In addition to `onCreate` calling `onExpand`, `onExpand` is also called when starting the App(s) e.g. `DBHelper.getHelper(this).onExpand(mDBDAO.getDB(), true);` – MikeT Sep 21 '17 at 20:16
  • @Anh-TuanMai previous comment explains (briefly). I've also updated the answer and also provided a real example. – MikeT Sep 21 '17 at 22:53
  • @Anh-TuanMai PS if you want these they are at [Mike-j-t/Modules](https://github.com/Mike-j-t/Modules). They aren't bullet-proof but they certainly serve me. PS you'd likely want sqlwords as well as the 4 DB????. – MikeT Sep 22 '17 at 08:00