|
|
|
@ -25,6 +25,8 @@ import com.arialyy.aria.core.download.DTaskWrapper; |
|
|
|
|
import com.arialyy.aria.core.download.DownloadEntity; |
|
|
|
|
import com.arialyy.aria.util.ALog; |
|
|
|
|
import java.lang.reflect.Field; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
@ -80,23 +82,29 @@ final class SqlHelper extends SQLiteOpenHelper { |
|
|
|
|
if (oldVersion < newVersion) { |
|
|
|
|
if (oldVersion < 31) { |
|
|
|
|
handle314AriaUpdate(db); |
|
|
|
|
} else if (oldVersion < 45) { |
|
|
|
|
handle360AriaUpdate(db); |
|
|
|
|
} else { |
|
|
|
|
handleDbUpdate(db); |
|
|
|
|
handleDbUpdate(db, null, null); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
|
|
|
|
//super.onDowngrade(db, oldVersion, newVersion);
|
|
|
|
|
if (oldVersion > newVersion) { |
|
|
|
|
handleDbUpdate(db); |
|
|
|
|
handleDbUpdate(db, null, null); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 处理数据库升级 |
|
|
|
|
* 处理数据库升级,该段代码无法修改表字段 |
|
|
|
|
* |
|
|
|
|
* @param modifyColumns 需要修改的表字段的映射,key为表名, |
|
|
|
|
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称 |
|
|
|
|
* @param delColumns 需要删除的表字段,key为表名,value{@code List<String>}为需要删除的字段列表 |
|
|
|
|
*/ |
|
|
|
|
private void handleDbUpdate(SQLiteDatabase db) { |
|
|
|
|
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns, |
|
|
|
|
Map<String, List<String>> delColumns) { |
|
|
|
|
if (db == null) { |
|
|
|
|
ALog.e("SqlHelper", "db 为 null"); |
|
|
|
|
return; |
|
|
|
@ -104,128 +112,152 @@ final class SqlHelper extends SQLiteOpenHelper { |
|
|
|
|
ALog.e("SqlHelper", "db已关闭"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
Set<String> tables = DBConfig.mapping.keySet(); |
|
|
|
|
for (String tableName : tables) { |
|
|
|
|
Class clazz = DBConfig.mapping.get(tableName); |
|
|
|
|
if (mDelegate.tableExists(db, clazz)) { |
|
|
|
|
String countColumnSql = "SELECT rowid FROM " + tableName; |
|
|
|
|
Cursor cursor = db.rawQuery(countColumnSql, null); |
|
|
|
|
int dbColumnNum = cursor.getColumnCount(); |
|
|
|
|
List<Field> fields = SqlUtil.getAllNotIgnoreField(clazz); |
|
|
|
|
int newEntityColumnNum = (fields == null || fields.isEmpty()) ? 0 : fields.size(); |
|
|
|
|
if (dbColumnNum != newEntityColumnNum) { |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
db.beginTransaction(); |
|
|
|
|
Set<String> tables = DBConfig.mapping.keySet(); |
|
|
|
|
for (String tableName : tables) { |
|
|
|
|
Class clazz = DBConfig.mapping.get(tableName); |
|
|
|
|
if (mDelegate.tableExists(db, clazz)) { |
|
|
|
|
db = mDelegate.checkDb(db); |
|
|
|
|
//备份数据
|
|
|
|
|
List<DbEntity> list = |
|
|
|
|
DelegateManager.getInstance().getDelegate(DelegateFind.class).findAllData(db, clazz); |
|
|
|
|
//修改表名为中介表名
|
|
|
|
|
String alertSql = "ALTER TABLE " + tableName + " RENAME TO " + tableName + "_temp"; |
|
|
|
|
//db.beginTransaction();
|
|
|
|
|
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName); |
|
|
|
|
db.execSQL(alertSql); |
|
|
|
|
|
|
|
|
|
//创建一个原本的表
|
|
|
|
|
//创建新表
|
|
|
|
|
mDelegate.createTable(db, clazz); |
|
|
|
|
//传入原来的数据
|
|
|
|
|
if (list != null && list.size() > 0) { |
|
|
|
|
DelegateUpdate update = DelegateManager.getInstance().getDelegate(DelegateUpdate.class); |
|
|
|
|
for (DbEntity entity : list) { |
|
|
|
|
update.insertData(db, entity); |
|
|
|
|
|
|
|
|
|
String sql = String.format("SELECT COUNT(*) FROM %s_temp", tableName); |
|
|
|
|
Cursor cursor = db.rawQuery(sql, null); |
|
|
|
|
cursor.moveToFirst(); |
|
|
|
|
long count = cursor.getLong(0); |
|
|
|
|
cursor.close(); |
|
|
|
|
|
|
|
|
|
if (count > 0) { |
|
|
|
|
// 获取所有表字段名称
|
|
|
|
|
Cursor columnC = |
|
|
|
|
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null); |
|
|
|
|
StringBuilder params = new StringBuilder(); |
|
|
|
|
|
|
|
|
|
while (columnC.moveToNext()) { |
|
|
|
|
String columnName = columnC.getString(columnC.getColumnIndex("name")); |
|
|
|
|
if (delColumns != null && delColumns.get(tableName) != null) { |
|
|
|
|
List<String> delColumn = delColumns.get(tableName); |
|
|
|
|
if (delColumn != null && !delColumn.isEmpty()) { |
|
|
|
|
if (delColumn.contains(columnName)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
params.append(columnName).append(","); |
|
|
|
|
} |
|
|
|
|
columnC.close(); |
|
|
|
|
|
|
|
|
|
String oldParamStr = params.toString(); |
|
|
|
|
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1); |
|
|
|
|
String newParamStr = oldParamStr; |
|
|
|
|
// 处理字段名称改变
|
|
|
|
|
if (modifyColumns != null) { |
|
|
|
|
//newParamStr = params.toString();
|
|
|
|
|
Map<String, String> columnMap = modifyColumns.get(tableName); |
|
|
|
|
if (columnMap != null && !columnMap.isEmpty()) { |
|
|
|
|
Set<String> keys = columnMap.keySet(); |
|
|
|
|
for (String key : keys) { |
|
|
|
|
if (newParamStr.contains(key)) { |
|
|
|
|
newParamStr = newParamStr.replace(key, columnMap.get(key)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//恢复数据
|
|
|
|
|
String insertSql = |
|
|
|
|
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr, |
|
|
|
|
oldParamStr, tableName); |
|
|
|
|
ALog.d(TAG, "insertSql = " + insertSql); |
|
|
|
|
db.execSQL(insertSql); |
|
|
|
|
} |
|
|
|
|
//删除中介表
|
|
|
|
|
mDelegate.dropTable(db, tableName + "_temp"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
db.setTransactionSuccessful(); |
|
|
|
|
} catch (Exception e) { |
|
|
|
|
ALog.e(TAG, e); |
|
|
|
|
} finally { |
|
|
|
|
db.endTransaction(); |
|
|
|
|
} |
|
|
|
|
//db.setTransactionSuccessful();
|
|
|
|
|
//db.endTransaction();
|
|
|
|
|
|
|
|
|
|
mDelegate.close(db); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 处理3.6以下版本的数据库升级 |
|
|
|
|
*/ |
|
|
|
|
private void handle360AriaUpdate(SQLiteDatabase db) { |
|
|
|
|
String[] taskTables = |
|
|
|
|
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
|
|
|
|
for (String taskTable : taskTables) { |
|
|
|
|
if (mDelegate.tableExists(db, taskTable)) { |
|
|
|
|
mDelegate.dropTable(db, taskTable); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Map<String, Map<String, String>> columnMap = new HashMap<>(); |
|
|
|
|
Map<String, String> map = new HashMap<>(); |
|
|
|
|
map.put("groupName", "groupHash"); |
|
|
|
|
columnMap.put("DownloadEntity", map); |
|
|
|
|
columnMap.put("DownloadGroupEntity", map); |
|
|
|
|
handleDbUpdate(db, columnMap, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 处理3.4版本之前数据库迁移,主要是修改子表外键字段对应的值 |
|
|
|
|
*/ |
|
|
|
|
private void handle314AriaUpdate(SQLiteDatabase db) { |
|
|
|
|
Set<String> tables = DBConfig.mapping.keySet(); |
|
|
|
|
Map<String, List<DbEntity>> map = new HashMap<>(); |
|
|
|
|
for (String tableName : tables) { |
|
|
|
|
Class clazz = DBConfig.mapping.get(tableName); |
|
|
|
|
|
|
|
|
|
String pColumn = SqlUtil.getPrimaryName(clazz); |
|
|
|
|
if (!TextUtils.isEmpty(pColumn)) { |
|
|
|
|
//删除所有主键为null的数据
|
|
|
|
|
String nullSql = |
|
|
|
|
"DELETE FROM " + tableName + " WHERE " + pColumn + " = '' OR " + pColumn + " IS NULL"; |
|
|
|
|
ALog.d(TAG, nullSql); |
|
|
|
|
db.execSQL(nullSql); |
|
|
|
|
|
|
|
|
|
//删除所有主键重复的数据
|
|
|
|
|
String repeatSql = "DELETE FROM " |
|
|
|
|
+ tableName |
|
|
|
|
+ " WHERE " |
|
|
|
|
+ pColumn |
|
|
|
|
+ " in (SELECT " |
|
|
|
|
+ pColumn |
|
|
|
|
+ " FROM " |
|
|
|
|
+ tableName |
|
|
|
|
+ " GROUP BY " + pColumn + " having count(" + pColumn + ") > 1)"; |
|
|
|
|
|
|
|
|
|
ALog.d(TAG, repeatSql); |
|
|
|
|
db.execSQL(repeatSql); |
|
|
|
|
String[] taskTables = |
|
|
|
|
new String[] { "UploadTaskEntity", "DownloadTaskEntity", "DownloadGroupTaskEntity" }; |
|
|
|
|
for (String taskTable : taskTables) { |
|
|
|
|
if (mDelegate.tableExists(db, taskTable)) { |
|
|
|
|
mDelegate.dropTable(db, taskTable); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//备份数据
|
|
|
|
|
List<DbEntity> list = |
|
|
|
|
DelegateManager.getInstance().getDelegate(DelegateFind.class).findAllData(db, clazz); |
|
|
|
|
|
|
|
|
|
map.put(tableName, list); |
|
|
|
|
|
|
|
|
|
//修改表名为中介表名
|
|
|
|
|
String alertSql = "ALTER TABLE " + tableName + " RENAME TO " + tableName + "_temp"; |
|
|
|
|
db.execSQL(alertSql); |
|
|
|
|
|
|
|
|
|
//创建一个原本的表
|
|
|
|
|
mDelegate.createTable(db, clazz); |
|
|
|
|
//插入数据,3.6版本后移除任务实体的保存
|
|
|
|
|
//if (list != null && list.size() > 0) {
|
|
|
|
|
// DelegateUpdate update = DelegateManager.getInstance().getDelegate(DelegateUpdate.class);
|
|
|
|
|
// try {
|
|
|
|
|
// for (DbEntity entity : list) {
|
|
|
|
|
// if (entity instanceof DTaskWrapper && ((DTaskWrapper) entity).isGroupTask()) {
|
|
|
|
|
// if (TextUtils.isEmpty(((DTaskWrapper) entity).getKey())) {
|
|
|
|
|
// ALog.w(TAG, "DownloadTaskEntity的key为空,将忽略该条数据");
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
// if (TextUtils.isEmpty(((DTaskWrapper) entity).getUrl())) {
|
|
|
|
|
// List<DbEntity> temp = map.get("DownloadEntity");
|
|
|
|
|
// boolean isRefresh = false;
|
|
|
|
|
// for (DbEntity dbEntity : temp) {
|
|
|
|
|
// if (((DownloadEntity) dbEntity).getDownloadPath()
|
|
|
|
|
// .equals(((DTaskWrapper) entity).getKey())) {
|
|
|
|
|
// ((DTaskWrapper) entity).setUrl(((DownloadEntity) dbEntity).getUrl());
|
|
|
|
|
// isRefresh = true;
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// if (isRefresh) {
|
|
|
|
|
// update.insertData(db, entity);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// } else {
|
|
|
|
|
// update.insertData(db, entity);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// } catch (Exception e) {
|
|
|
|
|
// ALog.e(TAG, ALog.getExceptionString(e));
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//删除中介表
|
|
|
|
|
mDelegate.dropTable(db, tableName + "_temp"); |
|
|
|
|
|
|
|
|
|
mDelegate.close(db); |
|
|
|
|
//删除所有主键为null和逐渐重复的数据
|
|
|
|
|
String[] tables = new String[] { "DownloadEntity", "DownloadGroupEntity" }; |
|
|
|
|
String[] keys = new String[] { "downloadPath", "groupName" }; |
|
|
|
|
int i = 0; |
|
|
|
|
for (String tableName : tables) { |
|
|
|
|
String pColumn = keys[i]; |
|
|
|
|
String nullSql = |
|
|
|
|
String.format("DELETE FROM %s WHERE %s='' OR %s IS NULL", tableName, pColumn, pColumn); |
|
|
|
|
ALog.d(TAG, nullSql); |
|
|
|
|
db.execSQL(nullSql); |
|
|
|
|
|
|
|
|
|
//删除所有主键重复的数据
|
|
|
|
|
String repeatSql = |
|
|
|
|
String.format( |
|
|
|
|
"DELETE FROM %s WHERE %s IN(SELECT %s FROM %s GROUP BY %s HAVING COUNT(%s) > 1)", |
|
|
|
|
tableName, pColumn, pColumn, tableName, pColumn, pColumn); |
|
|
|
|
|
|
|
|
|
ALog.d(TAG, repeatSql); |
|
|
|
|
db.execSQL(repeatSql); |
|
|
|
|
i++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
map.clear(); |
|
|
|
|
Map<String, Map<String, String>> modifyColumnMap = new HashMap<>(); |
|
|
|
|
Map<String, String> map = new HashMap<>(); |
|
|
|
|
map.put("groupName", "groupHash"); |
|
|
|
|
modifyColumnMap.put("DownloadEntity", map); |
|
|
|
|
modifyColumnMap.put("DownloadGroupEntity", map); |
|
|
|
|
|
|
|
|
|
Map<String, List<String>> delColumnMap = new HashMap<>(); |
|
|
|
|
List<String> dEntityDel = new ArrayList<>(); |
|
|
|
|
dEntityDel.add("taskKey"); |
|
|
|
|
delColumnMap.put("DownloadEntity", dEntityDel); |
|
|
|
|
List<String> dgEntityDel = new ArrayList<>(); |
|
|
|
|
dgEntityDel.add("subtask"); |
|
|
|
|
delColumnMap.put("DownloadGroupEntity", dgEntityDel); |
|
|
|
|
|
|
|
|
|
handleDbUpdate(db, modifyColumnMap, delColumnMap); |
|
|
|
|
} |
|
|
|
|
} |