Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62221769 authored by Suprabh Shukla's avatar Suprabh Shukla
Browse files

Added minimum supported version in SQLiteOpenHelper

Added a convenience mechanism to delete the whole database if it is of
a version that is so old that the application does not want to support
upgrading it. SQLiteOpenHelper now automatically deletes such a database
and creates a fresh one with the newest version provided. A callback
onBeforeDelete is added if the application wants to collect some data
from the db before it is deleted.

Test: Tested by upgrading contacts database using ContactsDatabaseHelper

Bug: 31559016
Change-Id: I3f924d247cdca2015c4244cc987de2538a086651
parent 1b219d06
Loading
Loading
Loading
Loading
+80 −22
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;
import java.io.File;

/**
 * A helper class to manage database creation and version management.
@@ -54,6 +55,7 @@ public abstract class SQLiteOpenHelper {
    private final String mName;
    private final CursorFactory mFactory;
    private final int mNewVersion;
    private final int mMinimumSupportedVersion;

    private SQLiteDatabase mDatabase;
    private boolean mIsInitializing;
@@ -96,6 +98,34 @@ public abstract class SQLiteOpenHelper {
     */
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
            DatabaseErrorHandler errorHandler) {
        this(context, name, factory, version, 0, errorHandler);
    }

    /**
     * Same as {@link #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)}
     * but also accepts an integer minimumSupportedVersion as a convenience for upgrading very old
     * versions of this database that are no longer supported. If a database with older version that
     * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
     * given name and version
     *
     * @param context to use to open or create the database
     * @param name the name of the database file, null for a temporary in-memory database
     * @param factory to use for creating cursor objects, null for default
     * @param version the required version of the database
     * @param minimumSupportedVersion the minimum version that is supported to be upgraded to
     *            {@code version} via {@link #onUpgrade}. If the current database version is lower
     *            than this, database is simply deleted and recreated with the version passed in
     *            {@code version}. {@link #onBeforeDelete} is called before deleting the database
     *            when this happens. This is 0 by default.
     * @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
     *            corruption, or null to use the default error handler.
     * @see #onBeforeDelete(SQLiteDatabase)
     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, DatabaseErrorHandler)
     * @see #onUpgrade(SQLiteDatabase, int, int)
     * @hide
     */
    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
            int minimumSupportedVersion, DatabaseErrorHandler errorHandler) {
        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);

        mContext = context;
@@ -103,6 +133,7 @@ public abstract class SQLiteOpenHelper {
        mFactory = factory;
        mNewVersion = version;
        mErrorHandler = errorHandler;
        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
    }

    /**
@@ -245,6 +276,18 @@ public abstract class SQLiteOpenHelper {
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }

                if (version > 0 && version < mMinimumSupportedVersion) {
                    File databaseFile = new File(db.getPath());
                    onBeforeDelete(db);
                    db.close();
                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
                        mIsInitializing = false;
                        return getDatabaseLocked(writable);
                    } else {
                        throw new IllegalStateException("Unable to delete obsolete database "
                                + mName + " with version " + version);
                    }
                } else {
                    db.beginTransaction();
                    try {
                        if (version == 0) {
@@ -262,6 +305,7 @@ public abstract class SQLiteOpenHelper {
                        db.endTransaction();
                    }
                }
            }

            onOpen(db);

@@ -292,24 +336,38 @@ public abstract class SQLiteOpenHelper {
    }

    /**
     * Called when the database connection is being configured, to enable features
     * such as write-ahead logging or foreign key support.
     * Called when the database connection is being configured, to enable features such as
     * write-ahead logging or foreign key support.
     * <p>
     * This method is called before {@link #onCreate}, {@link #onUpgrade},
     * {@link #onDowngrade}, or {@link #onOpen} are called.  It should not modify
     * the database except to configure the database connection as required.
     * </p><p>
     * This method should only call methods that configure the parameters of the
     * database connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled},
     * {@link SQLiteDatabase#setLocale}, {@link SQLiteDatabase#setMaximumSize},
     * or executing PRAGMA statements.
     * This method is called before {@link #onCreate}, {@link #onUpgrade}, {@link #onDowngrade}, or
     * {@link #onOpen} are called. It should not modify the database except to configure the
     * database connection as required.
     * </p>
     * <p>
     * This method should only call methods that configure the parameters of the database
     * connection, such as {@link SQLiteDatabase#enableWriteAheadLogging}
     * {@link SQLiteDatabase#setForeignKeyConstraintsEnabled}, {@link SQLiteDatabase#setLocale},
     * {@link SQLiteDatabase#setMaximumSize}, or executing PRAGMA statements.
     * </p>
     *
     * @param db The database.
     */
    public void onConfigure(SQLiteDatabase db) {}

    /**
     * Called before the database is deleted when the version returned by
     * {@link SQLiteDatabase#getVersion()} is lower than the minimum supported version passed (if at
     * all) while creating this helper. After the database is deleted, a fresh database with the
     * given version is created. This will be followed by {@link #onConfigure(SQLiteDatabase)} and
     * {@link #onCreate(SQLiteDatabase)} being called with a new SQLiteDatabase object
     *
     * @param db the database opened with this helper
     * @see #SQLiteOpenHelper(Context, String, CursorFactory, int, int, DatabaseErrorHandler)
     * @hide
     */
    public void onBeforeDelete(SQLiteDatabase db) {
    }

    /**
     * Called when the database is created for the first time. This is where the
     * creation of tables and the initial population of the tables should happen.