Android createFromAsset迁移,但保留特定列
我有一个测验应用程序,我有一个数据库,表中有所有问题,每个问题都有一个列Android createFromAsset迁移,但保留特定列,android,sqlite,android-room,Android,Sqlite,Android Room,我有一个测验应用程序,我有一个数据库,表中有所有问题,每个问题都有一个列已解决,如果答案正确,我会更新该列,因此我可以使用SQLWHERE过滤,只显示未解决的问题。 现在,每隔一段时间我就要纠正问题中的拼写错误,或者可能想添加一些新的,所以 如何在保留已解决的列的同时,将资产中已更正的数据库(questions.db)应用到用户设备上已保存的数据库中 我想到并尝试了以下事情,但没有成功: 目前,我使用自行编制的解决方案替换设备上的数据库(破坏性),但在更新之间保留已解决的信息 将已解决的信息(
已解决
,如果答案正确,我会更新该列,因此我可以使用SQLWHERE
过滤,只显示未解决的问题。
现在,每隔一段时间我就要纠正问题中的拼写错误,或者可能想添加一些新的,所以
如何在保留已解决的列的同时,将资产中已更正的数据库(questions.db)应用到用户设备上已保存的数据库中
我想到并尝试了以下事情,但没有成功:
- 目前,我使用自行编制的解决方案替换设备上的数据库(破坏性),但在更新之间保留已解决的信息
- 将已解决的信息(问题id已解决y/n)放在一个单独的表中,然后
左连接
以筛选未解决的问题,这只会使问题变得复杂
- 有一个额外的数据库来解决问题,似乎没有简单的方法来连接两个房间的数据库
因此,本质上,这可能是Room开发团队的灵感所在,我希望为createFromAsset提供一个适当的迁移策略,能够指定要保留的某些列/表。
感谢您迄今为止的出色工作,我非常喜欢使用Android Jetpack和Room!
另外,我很高兴能找到解决这个问题的方法:)我相信下面的方法可以满足您的需要
@Database(version = DatabaseConstants.DBVERSION, entities = {Question.class})
public abstract class QuestionDatabase extends RoomDatabase {
static final String DBNAME = DatabaseConstants.DBNAME;
abstract QuestionDao questionsDao();
public static QuestionDatabase getInstance(Context context) {
copyFromAssets(context,false);
if (getDBVersion(context,DatabaseConstants.DBNAME) < DatabaseConstants.DBVERSION) {
copyFromAssets(context,true);
}
return Room.databaseBuilder(context,QuestionDatabase.class,DBNAME)
.addCallback(callback)
.allowMainThreadQueries()
.addMigrations(Migration_1_2)
.build();
}
private static RoomDatabase.Callback callback = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db);
}
};
private static Migration Migration_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
private static boolean doesDatabaseExist(Context context) {
if (new File(context.getDatabasePath(DBNAME).getPath()).exists()) return true;
if (!(new File(context.getDatabasePath(DBNAME).getPath()).getParentFile()).exists()) {
new File(context.getDatabasePath(DBNAME).getPath()).getParentFile().mkdirs();
}
return false;
}
private static void copyFromAssets(Context context, boolean replaceExisting) {
boolean dbExists = doesDatabaseExist(context);
if (dbExists && !replaceExisting) return;
//First Copy
if (!replaceExisting) {
copyAssetFile(context);
return;
}
//Subsequent Copies
File originalDBPath = new File(context.getDatabasePath(DBNAME).getPath());
// Open and close the original DB so as to checkpoint the WAL file
SQLiteDatabase originalDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
originalDB.close();
//1. Rename original database
String preservedDBName = "preserved_" + DBNAME;
File preservedDBPath = new File (originalDBPath.getParentFile().getPath() + preservedDBName);
(new File(context.getDatabasePath(DBNAME).getPath()))
.renameTo(preservedDBPath);
//2. Copy the replacement database from the assets folder
copyAssetFile(context);
//3. Open the newly copied database
SQLiteDatabase copiedDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
SQLiteDatabase preservedDB = SQLiteDatabase.openDatabase(preservedDBPath.getPath(),null,SQLiteDatabase.OPEN_READONLY);
//4. get the orignal data to be preserved
Cursor csr = preservedDB.query(
DatabaseConstants.QUESTION_TABLENAME,DatabaseConstants.EXTRACT_COLUMNS,
null,null,null,null,null
);
//5. Apply preserved data to the newly copied data
copiedDB.beginTransaction();
ContentValues cv = new ContentValues();
while (csr.moveToNext()) {
cv.clear();
for (String s: DatabaseConstants.PRESERVED_COLUMNS) {
switch (csr.getType(csr.getColumnIndex(s))) {
case Cursor.FIELD_TYPE_INTEGER:
cv.put(s,csr.getLong(csr.getColumnIndex(s)));
break;
case Cursor.FIELD_TYPE_STRING:
cv.put(s,csr.getString(csr.getColumnIndex(s)));
break;
case Cursor.FIELD_TYPE_FLOAT:
cv.put(s,csr.getDouble(csr.getColumnIndex(s)));
break;
case Cursor.FIELD_TYPE_BLOB:
cv.put(s,csr.getBlob(csr.getColumnIndex(s)));
break;
}
}
copiedDB.update(
DatabaseConstants.QUESTION_TABLENAME,
cv,
DatabaseConstants.QUESTION_ID_COLUMN + "=?",
new String[]{
String.valueOf(
csr.getLong(
csr.getColumnIndex(DatabaseConstants.QUESTION_ID_COLUMN
)
)
)
}
);
}
copiedDB.setTransactionSuccessful();
copiedDB.endTransaction();
csr.close();
//6. Cleanup
copiedDB.close();
preservedDB.close();
preservedDBPath.delete();
}
private static void copyAssetFile(Context context) {
int buffer_size = 8192;
byte[] buffer = new byte[buffer_size];
int bytes_read = 0;
try {
InputStream fis = context.getAssets().open(DBNAME);
OutputStream os = new FileOutputStream(new File(context.getDatabasePath(DBNAME).getPath()));
while ((bytes_read = fis.read(buffer)) > 0) {
os.write(buffer,0,bytes_read);
}
os.flush();
os.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Unable to copy from assets");
}
}
private static int getDBVersion(Context context, String databaseName) {
SQLiteDatabase db = SQLiteDatabase.openDatabase( context.getDatabasePath(databaseName).getPath(),null,SQLiteDatabase.OPEN_READONLY);
int rv = db.getVersion();
db.close();
return rv;
}
}
因此,可以添加要保留的其他列(根据copyFromAssets方法中的5.的任何类型)。
还可以指定要提取的列,在上述情况下,ID列唯一地标识问题,以便在WHERE子句使用的已解决列之外提取问题
测试
已对上述各项进行了测试,以:-
起初的
- 当DBVERSION为1时,从资产复制数据库的第一个版本
- 请注意,本文件最初包含3个问题,根据
- 代码的一部分(在调用活动中,检查所有已解决的值是否为0,如果是,则使用id为2更改问题的已解决状态)
- 不复制数据库,但在子集运行中,当DBVERSION为1时,使用现有数据库。
- 第二个问题仍未解决
新的
- 将原始资源从重命名为以原始资源为前缀后,按如下方式编辑数据库,并将其复制到资源文件中:-
- 在不更改DBVERSION(仍然为1)的情况下运行,并且原始数据库仍在使用中
- 将DBVERSION更改为2后,运行将复制更改的资产文件并恢复/保留已解决状态
- 对于后续运行,新数据的已解决状态保持不变
用于测试调用活动,包括:-
public class MainActivity extends AppCompatActivity {
QuestionDatabase questionDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
questionDatabase = QuestionDatabase.getInstance(this);
int solvedCount = 0;
for (Question q: questionDatabase.questionsDao().getAll()) {
if (q.isSolved()) solvedCount++;
q.logQuestion();
}
if (solvedCount == 0) {
questionDatabase.questionsDao().setSolved(true,2);
}
for (Question q: questionDatabase.questionsDao().getAll()) {
q.logQuestion();
}
}
}
对于每次运行,它将所有问题输出到日志两次。在第一个问题之后,如果没有已解决的问题,它将使用id 2解决该问题
上次运行的输出为:-
附加-改进版
这是一个经批准的版本,适用于多个表和列。为了满足表的需要,添加了一个类TablePreserve,该类允许表、要保留的列、要提取的列以及where子句的列。根据:-
public class TablePreserve {
String tableName;
String[] preserveColumns;
String[] extractColumns;
String[] whereColumns;
public TablePreserve(String table, String[] preserveColumns, String[] extractColumns, String[] whereColumns) {
this.tableName = table;
this.preserveColumns = preserveColumns;
this.extractColumns = extractColumns;
this.whereColumns = whereColumns;
}
public String getTableName() {
return tableName;
}
public String[] getPreserveColumns() {
return preserveColumns;
}
public String[] getExtractColumns() {
return extractColumns;
}
public String[] getWhereColumns() {
return whereColumns;
}
}
您创建一个TablePreserve对象数组,这些对象在其中循环
public final class DatabaseConstants {
public static final String DBNAME = "question.db";
public static final int DBVERSION = 2;
public static final String QUESTION_TABLENAME = "question";
public static final String QUESTION_ID_COLUMN = "id";
public static final String QUESTION_QUESTION_COLUMN = QUESTION_TABLENAME;
public static final String QUESTION_ANSWER1_COLUMN = "answer1";
public static final String QUESTION_ANSWER2_COLUMN = "answer2";
public static final String QUESTION_ANSWER3_COLUMN = "answer3";
public static final String QUESTION_CORRECTANSWER_COLUMN = "correctAsnwer";
public static final String QUESTION_SOLVED_COLUMN = "solved";
public static final TablePreserve questionTablePreserve = new TablePreserve(
QUESTION_TABLENAME,
new String[]{QUESTION_SOLVED_COLUMN},
new String[]{QUESTION_ID_COLUMN,QUESTION_SOLVED_COLUMN},
new String[]{QUESTION_ID_COLUMN}
);
public static final TablePreserve[] TABLE_PRESERVELIST = new TablePreserve[] {
questionTablePreserve
};
}
然后问题数据库变成:-
@Database(version = DatabaseConstants.DBVERSION, entities = {Question.class})
public abstract class QuestionDatabase extends RoomDatabase {
static final String DBNAME = DatabaseConstants.DBNAME;
abstract QuestionDao questionsDao();
public static QuestionDatabase getInstance(Context context) {
if (!doesDatabaseExist(context)) {
copyFromAssets(context,false);
}
if (getDBVersion(context, DatabaseConstants.DBNAME) < DatabaseConstants.DBVERSION) {
copyFromAssets(context, true);
}
return Room.databaseBuilder(context,QuestionDatabase.class,DBNAME)
.addCallback(callback)
.allowMainThreadQueries()
.addMigrations(Migration_1_2)
.build();
}
private static RoomDatabase.Callback callback = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db);
}
};
private static Migration Migration_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
private static boolean doesDatabaseExist(Context context) {
if (new File(context.getDatabasePath(DBNAME).getPath()).exists()) return true;
if (!(new File(context.getDatabasePath(DBNAME).getPath()).getParentFile()).exists()) {
new File(context.getDatabasePath(DBNAME).getPath()).getParentFile().mkdirs();
}
return false;
}
private static void copyFromAssets(Context context, boolean replaceExisting) {
boolean dbExists = doesDatabaseExist(context);
if (dbExists && !replaceExisting) return;
//First Copy
if (!replaceExisting) {
copyAssetFile(context);
setDBVersion(context,DBNAME,DatabaseConstants.DBVERSION);
return;
}
//Subsequent Copies
File originalDBPath = new File(context.getDatabasePath(DBNAME).getPath());
// Open and close the original DB so as to checkpoint the WAL file
SQLiteDatabase originalDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
originalDB.close();
//1. Rename original database
String preservedDBName = "preserved_" + DBNAME;
File preservedDBPath = new File (originalDBPath.getParentFile().getPath() + File.separator + preservedDBName);
(new File(context.getDatabasePath(DBNAME).getPath()))
.renameTo(preservedDBPath);
//2. Copy the replacement database from the assets folder
copyAssetFile(context);
//3. Open the newly copied database
SQLiteDatabase copiedDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
SQLiteDatabase preservedDB = SQLiteDatabase.openDatabase(preservedDBPath.getPath(),null,SQLiteDatabase.OPEN_READONLY);
//4. Apply preserved data to the newly copied data
copiedDB.beginTransaction();
for (TablePreserve tp: DatabaseConstants.TABLE_PRESERVELIST) {
preserveTableColumns(
preservedDB,
copiedDB,
tp.getTableName(),
tp.getPreserveColumns(),
tp.getExtractColumns(),
tp.getWhereColumns(),
true
);
}
copiedDB.setVersion(DatabaseConstants.DBVERSION);
copiedDB.setTransactionSuccessful();
copiedDB.endTransaction();
//5. Cleanup
copiedDB.close();
preservedDB.close();
preservedDBPath.delete();
}
private static void copyAssetFile(Context context) {
int buffer_size = 8192;
byte[] buffer = new byte[buffer_size];
int bytes_read = 0;
try {
InputStream fis = context.getAssets().open(DBNAME);
OutputStream os = new FileOutputStream(new File(context.getDatabasePath(DBNAME).getPath()));
while ((bytes_read = fis.read(buffer)) > 0) {
os.write(buffer,0,bytes_read);
}
os.flush();
os.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Unable to copy from assets");
}
}
private static int getDBVersion(Context context, String databaseName) {
SQLiteDatabase db = SQLiteDatabase.openDatabase( context.getDatabasePath(databaseName).getPath(),null,SQLiteDatabase.OPEN_READONLY);
int rv = db.getVersion();
db.close();
return rv;
}
private static void setDBVersion(Context context, String databaseName, int version) {
SQLiteDatabase db = SQLiteDatabase.openDatabase( context.getDatabasePath(databaseName).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
}
private static boolean preserveTableColumns(
SQLiteDatabase originalDatabase,
SQLiteDatabase newDatabase,
String tableName,
String[] columnsToPreserve,
String[] columnsToExtract,
String[] whereClauseColumns,
boolean failWithException) {
StringBuilder sb = new StringBuilder();
Cursor csr = originalDatabase.query("sqlite_master",new String[]{"name"},"name=? AND type=?",new String[]{tableName,"table"},null,null,null);
if (!csr.moveToFirst()) {
sb.append("\n\tTable ").append(tableName).append(" not found in database ").append(originalDatabase.getPath());
}
csr = newDatabase.query("sqlite_master",new String[]{"name"},"name=? AND type=?",new String[]{tableName,"table"},null,null,null);
if (!csr.moveToFirst()) {
sb.append("\n\tTable ").append(tableName).append(" not found in database ").append(originalDatabase.getPath());
}
if (sb.length() > 0) {
if (failWithException) {
throw new RuntimeException("Both databases are required to have a table named " + tableName + sb.toString());
}
return false;
}
for (String pc: columnsToPreserve) {
boolean preserveColumnInExtractedColumn = false;
for (String ec: columnsToExtract) {
if (pc.equals(ec)) preserveColumnInExtractedColumn = true;
}
if (!preserveColumnInExtractedColumn) {
if (failWithException) {
StringBuilder sbpc = new StringBuilder().append("Column in Columns to Preserve not found in Columns to Extract. Cannot continuue." +
"\n\tColumns to Preserve are :-");
}
throw new RuntimeException("Column " + pc + " is not int the Columns to Extract.");
}
return false;
}
sb = new StringBuilder();
for (String c: whereClauseColumns) {
sb.append(c).append("=? ");
}
String[] whereargs = new String[whereClauseColumns.length];
csr = originalDatabase.query(tableName,columnsToExtract,sb.toString(),whereClauseColumns,null,null,null);
ContentValues cv = new ContentValues();
while (csr.moveToNext()) {
cv.clear();
for (String pc: columnsToPreserve) {
switch (csr.getType(csr.getColumnIndex(pc))) {
case Cursor.FIELD_TYPE_INTEGER:
cv.put(pc,csr.getLong(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_STRING:
cv.put(pc,csr.getString(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_FLOAT:
cv.put(pc,csr.getDouble(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_BLOB:
cv.put(pc,csr.getBlob(csr.getColumnIndex(pc)));
}
}
int waix = 0;
for (String wa: whereClauseColumns) {
whereargs[waix] = csr.getString(csr.getColumnIndex(wa));
}
newDatabase.update(tableName,cv,sb.toString(),whereargs);
}
csr.close();
return true;
}
}
@Database(version=DatabaseConstants.DBVERSION,entities={Question.class})
公共抽象类QuestionDatabase扩展了RoomDatabase{
静态最终字符串DBNAME=DatabaseConstants.DBNAME;
抽象问题dao questionsDao();
公共静态问题数据库getInstance(上下文){
如果(!doesDatabaseExist(上下文)){
copyFromAssets(上下文,false);
}
if(getDBVersion(context,DatabaseConstants.DBNAME)public final class DatabaseConstants {
public static final String DBNAME = "question.db";
public static final int DBVERSION = 2;
public static final String QUESTION_TABLENAME = "question";
public static final String QUESTION_ID_COLUMN = "id";
public static final String QUESTION_QUESTION_COLUMN = QUESTION_TABLENAME;
public static final String QUESTION_ANSWER1_COLUMN = "answer1";
public static final String QUESTION_ANSWER2_COLUMN = "answer2";
public static final String QUESTION_ANSWER3_COLUMN = "answer3";
public static final String QUESTION_CORRECTANSWER_COLUMN = "correctAsnwer";
public static final String QUESTION_SOLVED_COLUMN = "solved";
public static final TablePreserve questionTablePreserve = new TablePreserve(
QUESTION_TABLENAME,
new String[]{QUESTION_SOLVED_COLUMN},
new String[]{QUESTION_ID_COLUMN,QUESTION_SOLVED_COLUMN},
new String[]{QUESTION_ID_COLUMN}
);
public static final TablePreserve[] TABLE_PRESERVELIST = new TablePreserve[] {
questionTablePreserve
};
}
@Database(version = DatabaseConstants.DBVERSION, entities = {Question.class})
public abstract class QuestionDatabase extends RoomDatabase {
static final String DBNAME = DatabaseConstants.DBNAME;
abstract QuestionDao questionsDao();
public static QuestionDatabase getInstance(Context context) {
if (!doesDatabaseExist(context)) {
copyFromAssets(context,false);
}
if (getDBVersion(context, DatabaseConstants.DBNAME) < DatabaseConstants.DBVERSION) {
copyFromAssets(context, true);
}
return Room.databaseBuilder(context,QuestionDatabase.class,DBNAME)
.addCallback(callback)
.allowMainThreadQueries()
.addMigrations(Migration_1_2)
.build();
}
private static RoomDatabase.Callback callback = new Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
}
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
@Override
public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
super.onDestructiveMigration(db);
}
};
private static Migration Migration_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
}
};
private static boolean doesDatabaseExist(Context context) {
if (new File(context.getDatabasePath(DBNAME).getPath()).exists()) return true;
if (!(new File(context.getDatabasePath(DBNAME).getPath()).getParentFile()).exists()) {
new File(context.getDatabasePath(DBNAME).getPath()).getParentFile().mkdirs();
}
return false;
}
private static void copyFromAssets(Context context, boolean replaceExisting) {
boolean dbExists = doesDatabaseExist(context);
if (dbExists && !replaceExisting) return;
//First Copy
if (!replaceExisting) {
copyAssetFile(context);
setDBVersion(context,DBNAME,DatabaseConstants.DBVERSION);
return;
}
//Subsequent Copies
File originalDBPath = new File(context.getDatabasePath(DBNAME).getPath());
// Open and close the original DB so as to checkpoint the WAL file
SQLiteDatabase originalDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
originalDB.close();
//1. Rename original database
String preservedDBName = "preserved_" + DBNAME;
File preservedDBPath = new File (originalDBPath.getParentFile().getPath() + File.separator + preservedDBName);
(new File(context.getDatabasePath(DBNAME).getPath()))
.renameTo(preservedDBPath);
//2. Copy the replacement database from the assets folder
copyAssetFile(context);
//3. Open the newly copied database
SQLiteDatabase copiedDB = SQLiteDatabase.openDatabase(originalDBPath.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
SQLiteDatabase preservedDB = SQLiteDatabase.openDatabase(preservedDBPath.getPath(),null,SQLiteDatabase.OPEN_READONLY);
//4. Apply preserved data to the newly copied data
copiedDB.beginTransaction();
for (TablePreserve tp: DatabaseConstants.TABLE_PRESERVELIST) {
preserveTableColumns(
preservedDB,
copiedDB,
tp.getTableName(),
tp.getPreserveColumns(),
tp.getExtractColumns(),
tp.getWhereColumns(),
true
);
}
copiedDB.setVersion(DatabaseConstants.DBVERSION);
copiedDB.setTransactionSuccessful();
copiedDB.endTransaction();
//5. Cleanup
copiedDB.close();
preservedDB.close();
preservedDBPath.delete();
}
private static void copyAssetFile(Context context) {
int buffer_size = 8192;
byte[] buffer = new byte[buffer_size];
int bytes_read = 0;
try {
InputStream fis = context.getAssets().open(DBNAME);
OutputStream os = new FileOutputStream(new File(context.getDatabasePath(DBNAME).getPath()));
while ((bytes_read = fis.read(buffer)) > 0) {
os.write(buffer,0,bytes_read);
}
os.flush();
os.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Unable to copy from assets");
}
}
private static int getDBVersion(Context context, String databaseName) {
SQLiteDatabase db = SQLiteDatabase.openDatabase( context.getDatabasePath(databaseName).getPath(),null,SQLiteDatabase.OPEN_READONLY);
int rv = db.getVersion();
db.close();
return rv;
}
private static void setDBVersion(Context context, String databaseName, int version) {
SQLiteDatabase db = SQLiteDatabase.openDatabase( context.getDatabasePath(databaseName).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
db.setVersion(version);
db.close();
}
private static boolean preserveTableColumns(
SQLiteDatabase originalDatabase,
SQLiteDatabase newDatabase,
String tableName,
String[] columnsToPreserve,
String[] columnsToExtract,
String[] whereClauseColumns,
boolean failWithException) {
StringBuilder sb = new StringBuilder();
Cursor csr = originalDatabase.query("sqlite_master",new String[]{"name"},"name=? AND type=?",new String[]{tableName,"table"},null,null,null);
if (!csr.moveToFirst()) {
sb.append("\n\tTable ").append(tableName).append(" not found in database ").append(originalDatabase.getPath());
}
csr = newDatabase.query("sqlite_master",new String[]{"name"},"name=? AND type=?",new String[]{tableName,"table"},null,null,null);
if (!csr.moveToFirst()) {
sb.append("\n\tTable ").append(tableName).append(" not found in database ").append(originalDatabase.getPath());
}
if (sb.length() > 0) {
if (failWithException) {
throw new RuntimeException("Both databases are required to have a table named " + tableName + sb.toString());
}
return false;
}
for (String pc: columnsToPreserve) {
boolean preserveColumnInExtractedColumn = false;
for (String ec: columnsToExtract) {
if (pc.equals(ec)) preserveColumnInExtractedColumn = true;
}
if (!preserveColumnInExtractedColumn) {
if (failWithException) {
StringBuilder sbpc = new StringBuilder().append("Column in Columns to Preserve not found in Columns to Extract. Cannot continuue." +
"\n\tColumns to Preserve are :-");
}
throw new RuntimeException("Column " + pc + " is not int the Columns to Extract.");
}
return false;
}
sb = new StringBuilder();
for (String c: whereClauseColumns) {
sb.append(c).append("=? ");
}
String[] whereargs = new String[whereClauseColumns.length];
csr = originalDatabase.query(tableName,columnsToExtract,sb.toString(),whereClauseColumns,null,null,null);
ContentValues cv = new ContentValues();
while (csr.moveToNext()) {
cv.clear();
for (String pc: columnsToPreserve) {
switch (csr.getType(csr.getColumnIndex(pc))) {
case Cursor.FIELD_TYPE_INTEGER:
cv.put(pc,csr.getLong(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_STRING:
cv.put(pc,csr.getString(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_FLOAT:
cv.put(pc,csr.getDouble(csr.getColumnIndex(pc)));
break;
case Cursor.FIELD_TYPE_BLOB:
cv.put(pc,csr.getBlob(csr.getColumnIndex(pc)));
}
}
int waix = 0;
for (String wa: whereClauseColumns) {
whereargs[waix] = csr.getString(csr.getColumnIndex(wa));
}
newDatabase.update(tableName,cv,sb.toString(),whereargs);
}
csr.close();
return true;
}
}