package org.commcare.models.database.app; import android.content.Context; import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteException; import net.sqlcipher.database.SQLiteOpenHelper; import org.commcare.engine.resource.AndroidResourceManager; import org.commcare.models.database.AndroidTableBuilder; import org.commcare.models.database.DbUtil; import org.commcare.android.database.app.models.UserKeyRecord; import org.commcare.modern.database.DatabaseIndexingUtils; import org.commcare.resources.model.Resource; import org.javarosa.core.model.instance.FormInstance; /** * The helper for opening/updating the global (unencrypted) db space for * CommCare. * * @author ctsims */ public class DatabaseAppOpenHelper extends SQLiteOpenHelper { /** * Version History * V.2 - Added recovery table * V.3 - Upgraded Resource models to have an optional descriptor field * V.4 - Table parent resource indices * V.5 - Added numbers table * V.6 - Added temporary upgrade table for ease of checking for new updates * V.7 - Update serialized fixtures in db to use new schema * V.8 - Add fields to UserKeyRecord to support PIN auth */ private static final int DB_VERSION_APP = 8; private static final String DB_LOCATOR_PREF_APP = "database_app_"; private final Context context; private final String mAppId; public DatabaseAppOpenHelper(Context context, String appId) { super(context, getDbName(appId), null, DB_VERSION_APP); this.mAppId = appId; this.context = context; } public static String getDbName(String appId) { return DB_LOCATOR_PREF_APP + appId; } @Override public void onCreate(SQLiteDatabase database) { try { database.beginTransaction(); AndroidTableBuilder builder = new AndroidTableBuilder("GLOBAL_RESOURCE_TABLE"); builder.addData(new Resource()); database.execSQL(builder.getTableCreateString()); builder = new AndroidTableBuilder("UPGRADE_RESOURCE_TABLE"); builder.addData(new Resource()); database.execSQL(builder.getTableCreateString()); builder = new AndroidTableBuilder(AndroidResourceManager.TEMP_UPGRADE_TABLE_KEY); builder.addData(new Resource()); database.execSQL(builder.getTableCreateString()); builder = new AndroidTableBuilder("RECOVERY_RESOURCE_TABLE"); builder.addData(new Resource()); database.execSQL(builder.getTableCreateString()); builder = new AndroidTableBuilder("fixture"); builder.addFileBackedData(new FormInstance()); database.execSQL(builder.getTableCreateString()); DbUtil.createOrphanedFileTable(database); builder = new AndroidTableBuilder(UserKeyRecord.class); database.execSQL(builder.getTableCreateString()); database.execSQL(indexOnTableWithPGUIDCommand("global_index_id", "GLOBAL_RESOURCE_TABLE")); database.execSQL(indexOnTableWithPGUIDCommand("upgrade_index_id", "UPGRADE_RESOURCE_TABLE")); database.execSQL(indexOnTableWithPGUIDCommand("recovery_index_id", "RECOVERY_RESOURCE_TABLE")); database.execSQL(indexOnTableWithPGUIDCommand("temp_upgrade_index_id", AndroidResourceManager.TEMP_UPGRADE_TABLE_KEY)); DbUtil.createNumbersTable(database); database.setTransactionSuccessful(); } finally { database.endTransaction(); } } public static String indexOnTableWithPGUIDCommand(String indexName, String tableName) { return DatabaseIndexingUtils.indexOnTableCommand(indexName, tableName, Resource.META_INDEX_PARENT_GUID); } @Override public SQLiteDatabase getWritableDatabase(String key) { try { return super.getWritableDatabase(key); } catch (SQLiteException sqle) { DbUtil.trySqlCipherDbUpdate(key, context, getDbName(mAppId)); return super.getWritableDatabase(key); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { new AppDatabaseUpgrader(context).upgrade(db, oldVersion, newVersion); } }