Я полагаю, что вы могли бы использовать следующее, которое берет два файла и сравнивает схему (sqlite_master) между этими двумя на основе запроса, который объединяет две группы по столбцам name, type и sql (если они являютсято же самое, тогда было бы 2 на группу) и выводит те, для которых нет 2 строк (то есть несоответствие). Если в возвращенном курсоре нет строк, то совпадение схемы.
public class CompareDBSchemas {
public static boolean areDBSchemasEqual(File db1File, File db2File, boolean compareSizes) {
boolean rv = true;
if (!(db1File.exists() && db2File.exists())) return false;
if (compareSizes) {
if (db1File.length() != db2File.length()) return false;
}
SQLiteDatabase db1 = SQLiteDatabase.openDatabase(db1File.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
db1.execSQL("ATTACH '" +
db2File.getPath() + "' AS other");
/*
WITH cte AS (SELECT * FROM main.sqlite_master UNION ALL SELECT * FROM other.sqlite_master)
SELECT * FROM cte GROUP BY type,name,sql HAVING count() <> 2
*/
Cursor csr = db1.rawQuery("WITH cte AS (" +
"SELECT * FROM main.sqlite_master UNION ALL SELECT * FROM other.sqlite_master" +
") " +
"SELECT * FROM cte GROUP BY type,name,sql HAVING count() <> 2 ",
null
);
if (csr.getCount() > 0) {
rv = false;
}
csr.close();
db1.close();
return rv;
}
public static boolean areDBSchemasEqual(File db1File, File db2File) {
return areDBSchemasEqual(db1File,db2File,false);
}
}
- Обратите внимание, что в приведенном выше есть опция для определения различий в размерах базы данных, которая может обнаруживать измененные данные, а не только изменение схемы.
Пример использования
Ниже показано, как используется выше, когда создаются 3 базы данных, первая и вторая имеют одинаковую схему, а третья отличается (добавлен дополнительный столбец).
DatabseHlpr.java
public class DatabaseHlpr extends SQLiteOpenHelper {
public static final String TABLE_NAME = "mytable";
public static final String MYTABLE_COL_ID = BaseColumns._ID;
public static final String MYTABLE_COL_COMMON = "common";
public static final String MYTABLE_COL_SCHEMA1ONLY = "schema1only";
private int mSchema;
private SQLiteDatabase mDB;
public DatabaseHlpr(@Nullable Context context, @Nullable String name, int schema) {
super(context, name, null,1);
this.mSchema = schema;
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
switch (mSchema) {
case 1:
useSchema1(db);
break;
default:
useSchema0(db);
}
}
private void useSchema1(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
MYTABLE_COL_ID + " INTEGER PRIMARY KEY, " +
MYTABLE_COL_COMMON + " TEXT, " +
MYTABLE_COL_SCHEMA1ONLY + " TEXT " +
")");
}
private void useSchema0(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(" +
MYTABLE_COL_ID + " INTEGER PRIMARY KEY, " +
MYTABLE_COL_COMMON + " TEXT" +
")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
static final String DB1NAME = "db1", DB2NAME = "db2", DB3NAME = "db3";
DatabaseHlpr mDB1Hlpr, mDB2Hlpr, mDB3Hlpr;
File db1File, db2File,db3File;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDB1Hlpr = new DatabaseHlpr(this,DB1NAME,0);
mDB2Hlpr = new DatabaseHlpr(this,DB2NAME,0);
mDB3Hlpr = new DatabaseHlpr(this,DB3NAME,1);
mDB1Hlpr.close();
mDB2Hlpr.close();
mDB3Hlpr.close();
db1File = new File(this.getDatabasePath(DB1NAME).getPath());
db2File = new File(this.getDatabasePath(DB2NAME).getPath());
db3File = new File(this.getDatabasePath(DB3NAME).getPath());
String result = " the same ";
if (!CompareDBSchemas.areDBSchemasEqual(db1File,db2File,false)) {
result = " NOT the same ";
}
Log.d("RESULTINFO",
"Database Schemas are " + result +
" for " +
"\n\t" +db1File.getPath() +
"\n and \n\t" + db2File.getPath()
);
result = " the same ";
if (!CompareDBSchemas.areDBSchemasEqual(db1File,db3File)) {
result = " NOT the same ";
}
Log.d("RESULTINFO",
"Database Schemas are " + result +
" for " +
"\n\t" +db1File.getPath() +
"\n and \n\t" + db3File.getPath()
);
}
}
- Обратите внимание, что выше было написано, чтобы продемонстрировать процесс сравнения и, таким образом, поиск файлов является простым и удобным,Он не предназначен для отражения того, как будут извлечены файлы.
Результат: -
2019-10-27 07:19:23.688 28976-28976/aso.so58566618dbcompareschema D/RESULTINFO: Database Schemas are the same for
/data/user/0/aso.so58566618dbcompareschema/databases/db1
and
/data/user/0/aso.so58566618dbcompareschema/databases/db2
2019-10-27 07:19:23.693 28976-28976/aso.so58566618dbcompareschema D/RESULTINFO: Database Schemas are NOT the same for
/data/user/0/aso.so58566618dbcompareschema/databases/db1
and
/data/user/0/aso.so58566618dbcompareschema/databases/db3
ДОПОЛНИТЕЛЬНО
Если вы хотели проверить количество строк(данные вставлены или удалены) и фактические данные (данные изменены при обновлении), затем можно использовать следующую адаптацию класса CompareDBSchemas: -
public class CompareDBSchemas {
private static final String
SQLITE_MASTER = "sqlite_master",
SQLITE_MASTER_TYPE_COLUMN = "type",
SQLITE_MASTER_NAME_COLUMN = "name",
SQLITE_MASTER_SQL_COLUMN = "sql",
SQLITE_MASTER_TABLE_TYPE = "table",
SQLITE_SYSTEMTABLES = "sqlite_",
ANDROID_METADATA = "android_metadata",
CTE_NAME = "cte", MAIN_SCHEMA = "main", OTHER_SCHEMA = "other"
;
public static boolean areDBSchemasEqual(File db1File, File db2File, boolean compareSizes, boolean compareRowCounts, boolean compareData) {
boolean rv = true;
if (!(db1File.exists() && db2File.exists())) return false;
if (compareSizes) {
if (db1File.length() != db2File.length()) return false;
}
SQLiteDatabase db1 = SQLiteDatabase.openDatabase(db1File.getPath(),null,SQLiteDatabase.OPEN_READWRITE);
db1.beginTransaction();
db1.execSQL("ATTACH '" +
db2File.getPath() + "' AS " + OTHER_SCHEMA);
/*
WITH cte AS (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_master)
SELECT * FROM cte GROUP BY type,name,sql HAVING count() <> 2
*/
Cursor csr = db1.rawQuery("WITH " + CTE_NAME + " AS (" +
"SELECT * FROM " + MAIN_SCHEMA + "." + SQLITE_MASTER +
" UNION ALL " +
"SELECT * FROM " + OTHER_SCHEMA + "." + SQLITE_MASTER +
") " +
"SELECT * FROM " + CTE_NAME +
" GROUP BY " +
SQLITE_MASTER_TYPE_COLUMN + "," +
SQLITE_MASTER_NAME_COLUMN + "," +
SQLITE_MASTER_SQL_COLUMN +
" HAVING count() <> 2 ",
null
);
if (csr.getCount() > 0) {
rv = false;
}
if (compareRowCounts && rv) {
csr = db1.rawQuery("SELECT * FROM main." + SQLITE_MASTER +
" WHERE " + SQLITE_MASTER_TYPE_COLUMN +
" = '" + SQLITE_MASTER_TABLE_TYPE +
"' AND (" + SQLITE_MASTER_NAME_COLUMN +
" NOT LIKE '" + SQLITE_SYSTEMTABLES +
"%' AND " + SQLITE_MASTER_NAME_COLUMN +
" <> '" + ANDROID_METADATA + "')",null);
while(csr.moveToNext()) {
if (
DatabaseUtils.queryNumEntries(db1,MAIN_SCHEMA +"." + csr.getString(csr.getColumnIndex(SQLITE_MASTER_NAME_COLUMN))) ==
DatabaseUtils.queryNumEntries(db1,OTHER_SCHEMA + "." + csr.getString(csr.getColumnIndex(SQLITE_MASTER_NAME_COLUMN)))
) continue;
rv = false;
break;
}
}
if (compareData && rv) {
csr.moveToPosition(-1);
while (csr.moveToNext()) {
if (
isTableDataTheSame(db1,csr.getString(csr.getColumnIndex(SQLITE_MASTER_NAME_COLUMN)))
) continue;
rv = false;
break;
}
}
db1.endTransaction();
csr.close();
db1.close();
return rv;
}
private static boolean isTableDataTheSame(SQLiteDatabase db, String table) {
boolean rv = true;
Cursor csr = db.rawQuery("PRAGMA table_info("+ table +")",null);
StringBuilder columnConcat = new StringBuilder();
while (csr.moveToNext()) {
if (columnConcat.length() > 0) columnConcat.append("||");
columnConcat.append(csr.getString(csr.getColumnIndex(SQLITE_MASTER_NAME_COLUMN)));
}
csr = db.rawQuery("WITH " + CTE_NAME +
" AS (" +
" SELECT " + columnConcat.toString() +
" AS comparison FROM " + MAIN_SCHEMA + "." + table +
" UNION ALL SELECT " + columnConcat.toString() + " FROM " + OTHER_SCHEMA + "." + table +
") SELECT * FROM " + CTE_NAME +
" GROUP BY comparison HAVING count() <> 2",
null
);
if (csr.getCount() > 0) {
rv = false;
}
csr.close();
return rv;
}
public static boolean areDBSchemasEqual(File db1File, File db2File) {
return areDBSchemasEqual(db1File,db2File,false,false,false);
}
}