Good scheme to delete a database file in SQLiteOpenHelper.onDowngrade ()

I have an existing database based on SQLiteOpenHelper that has several versions and code to update it, and this works fine. But if the user installs an older version of the application (which expects a lower version of the database), it is currently crashing - using ContentProvider with it cannot access the database. I would like to prevent it from crashing, but I don't want to actually downgrade the database - adding code for this would be a pain. Deleting all tables will certainly work, but starting with a new file, you will clear and reduce the likelihood of errors.

What about what the database helper looks like - nothing special

 public class MyDbHelper extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 3; private static final String DATABASE_NAME = "my.db"; public MyDbHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { onUpgrade(db, 0, DATABASE_VERSION); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (newVersion < 1) db.execSQL("CREATE TABLE A..."); if (newVersion < 2) db.execSQL("CREATE TABLE B..."); if (newVersion < 3) db.execSQL("CREATE TABLE C..."); } @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { // I'd like to delete the database here // the only problem is that I can't from here // since this is called in the middle of getWritableDatabase() // and SQLiteDatabase has no .recreate() method. } } 

Possible ways that I did for this:

  • Do it from the outside: catch the exceptions in the ContentProvider , delete the file and ask to open the database again. - I do not like this, because it is not the responsibility of the provider.
  • Replacing SQLiteOpenHelper my own copy of this class, which deletes the file instead of calling onDowngrade . The problem is that it uses private parts of the SQLiteDatabase package (for example, .lock() ), which I cannot replace without duplicating SQLiteDatabase too (which will probably lead to duplication of the entire sqlite package).

Is there any good approach to this, or do I need to follow the DROP TABLES path, for example. as described here ?

+6
source share
1 answer

I figured out a way that works well by extending SQLiteOpenHelper, and all I need to do in MyDbHelper is an extension of this class.

 public abstract class DeletingSQLiteOpenHelper extends SQLiteOpenHelper { private static final String TAG = DeletingSQLiteOpenHelper.class.getSimpleName(); private final File mDatabaseFile; public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { super(context, name, factory, version, errorHandler); mDatabaseFile = context.getDatabasePath(name); } public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); mDatabaseFile = context.getDatabasePath(name); } @Override public synchronized SQLiteDatabase getWritableDatabase() { try { return super.getWritableDatabase(); } catch (SQLiteDowngradeFailedException e) { // that our notification } // try to delete the file mDatabaseFile.delete() // now return a freshly created database return super.getWritableDatabase(); } @Override public final void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { // throwing a custom Exception to catch it in getWritableDatabase throw new SQLiteDowngradeFailedException(); } // that the exception static class SQLiteDowngradeFailedException extends SQLiteException { public SQLiteDowngradeFailedException() {} public SQLiteDowngradeFailedException(String error) { super(error); } } } 
+9
source

Source: https://habr.com/ru/post/911202/


All Articles