5

Can someone explain how the onUpgrade function is called within the SqliteDbOpenHelper class. I'm opening my database but it's not calling the onUpgrade even though I've changed the DB_VERSION.

See following code:

public class DbHelper extends SQLiteOpenHelper {
    private static final String TAG = "DbHelper";

    static final String DB_NAME = "caddata.sqlite";
    static final int DB_VERSION = 4;

    private static String DB_PATH = "";
    private Context myContext;
    private SQLiteDatabase myDataBase;

    public DbHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        this.myContext = context;

        DB_PATH = "/data/data/"
                + context.getApplicationContext().getPackageName()
                + "/databases/";            
    }

    public DbHelper open() throws SQLException {        
        myDataBase =  getWritableDatabase();

        Log.d(TAG, "DbHelper Opening Version: " +  this.myDataBase.getVersion());
        return this;
    }

    @Override
    public synchronized void close() {

        if (myDataBase != null)
            myDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d(TAG, "onCreate called");

        try {           
            createDataBase();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if ( newVersion > oldVersion)
        {
            Log.d(TAG, "New database version exists for upgrade.");         
            try {
                Log.d(TAG, "Copying database...");
                copyDataBase();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }       
        }
    }

    public void createDataBase() throws IOException {

        boolean dbExist = checkDataBase();

        if (!dbExist) {         

            try {
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }

        openDataBaseForRead();
    }


    private boolean checkDataBase() {

        SQLiteDatabase checkDB = null;

        try {
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null,
                    SQLiteDatabase.OPEN_READONLY
                            | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
            Log.d(TAG, "db exists");
        } catch (SQLiteException e) {
            // database does't exist yet.
            Log.d(TAG, "db doesn't exist");

        }

        if (checkDB != null) {
            checkDB.close();            
        }

        return checkDB != null ? true : false;
    }


    private void copyDataBase() throws IOException {

        // Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        // Path to the just created empty db
        String outFileName = DB_PATH + DB_NAME;

        // Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);

        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[2048];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

        myDataBase.setVersion(DB_VERSION);
    }

    public void openDataBaseForRead() throws SQLException {

        // Open the database
        String myPath = DB_PATH + DB_NAME;      
        myDataBase = SQLiteDatabase.openDatabase(myPath, null,  SQLiteDatabase.OPEN_READONLY);
    }

    public void openDataBaseForWrite() throws SQLException {

        // Open the database
        String myPath = DB_PATH + DB_NAME;      
        myDataBase = SQLiteDatabase.openDatabase(myPath, null,  SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS );
    }


}

Also see my question detailed here: Why is onUpgrade() not being invoked on Android sqlite database? for which I didn't get a response.

My main activity opens the database from the helper. It was my assumption that just opening the database will cause onUpgrade() function to be called:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DbHelper myDbHelper =  new DbHelper(this);

        try {

            myDbHelper.createDataBase();

        } catch (IOException ioe) {

            throw new Error("Unable to create database");

        }

        try {

            myDbHelper.openDataBaseForRead();

        }catch(SQLException sqle){

            throw sqle;

        }
}
Community
  • 1
  • 1
jaffa
  • 26,770
  • 50
  • 178
  • 289

3 Answers3

1

In my opinion, the onCreate() and onUpgrade() function work only when you open a database with the SQLiteOpenHelper. that means you should call the function getWritableDatabase() or getReadbleDatabase() to open the database and then maybe it can works normally.

Rathakrishnan Ramasamy
  • 1,612
  • 2
  • 25
  • 46
Aderly
  • 11
  • 1
0

(Updated after Chris's comment) Pure logic suggests that DB must be upgraded each time it opens with a greater version. Never checked this case, but, as far as I know, onUpgrade() is always invoked during application upgrade when database version has been changed.

Ash
  • 1,701
  • 13
  • 18
  • 2
    It checks every time the DB is opened. Not during application upgrades. – Pedantic Oct 05 '11 at 12:51
  • My point was you can replace a new db file with an old one, run your app and it'll be upgraded on access without upgrading your actual app. Wasn't trying to be pedantic. – Pedantic Oct 05 '11 at 13:06
  • I got your point and appreciate the new information. Never checked the case of upgrading the database without upgrading the app, and since it didn't work for jaffa, I suggested to check out 'upgrade' option. – Ash Oct 05 '11 at 13:16
  • It happen during a call to either getReadableDatabase() or getWriteableDatabase(). http://stackoverflow.com/a/8621774/304270 – Ewoks Feb 13 '13 at 07:02
0

SQLlite database files have an internal version #. If the API tries to open an existing file and the version is less than some specified one, onUpgrade is called so you can handle it.

Pedantic
  • 5,032
  • 2
  • 24
  • 37
  • Ok, so why am I not seeing the OnUpgrade function called even though I've incremented the database version? – jaffa Oct 05 '11 at 12:58
  • Readable DBs can't be upgraded. Your activity only opens it for read, that may be one reason. – Pedantic Oct 05 '11 at 13:09
  • I changed the call in the startup activity to call openDataBaseForWrite(). My database version set inside the DbHelper class is also set to 2. However, when I call GetVersion() on the database object it returns 0. Why isn't onUpgrade being called then? – jaffa Oct 06 '11 at 12:09
  • I am having a similar issue, and during my troubleshooting I am attempting to see where exactly this "internal version #" is. I pull the database from the emulator (data/data/XXXX/databases/databasename and then look at the file with a database analyzer such as sqliteman. I do not see any version info. Thanks for any insight. – Mike Dec 30 '11 at 11:50
  • @Mike if you open it up in, eg. SQLite Manager (a plugin for firefox) and go to the DB Settings tab you can see the version #. – Pedantic Dec 30 '11 at 15:08