Refactor join between installed apps and packages.
This commit is contained in:
parent
b729f4dc84
commit
bb96cdeff9
@ -250,7 +250,7 @@ public class AppProvider extends FDroidProvider {
|
||||
join(
|
||||
InstalledAppTable.NAME,
|
||||
"installed",
|
||||
"installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
|
||||
"installed." + InstalledAppTable.Cols.PACKAGE_ID + " = " + PackageTable.NAME + "." + PackageTable.Cols.ROW_ID);
|
||||
requiresInstalledTable = true;
|
||||
}
|
||||
}
|
||||
@ -270,7 +270,7 @@ public class AppProvider extends FDroidProvider {
|
||||
leftJoin(
|
||||
InstalledAppTable.NAME,
|
||||
"installed",
|
||||
"installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = " + PackageTable.NAME + "." + PackageTable.Cols.PACKAGE_NAME);
|
||||
"installed." + InstalledAppTable.Cols.PACKAGE_ID + " = " + PackageTable.NAME + "." + PackageTable.Cols.ROW_ID);
|
||||
requiresInstalledTable = true;
|
||||
}
|
||||
}
|
||||
@ -959,8 +959,9 @@ public class AppProvider extends FDroidProvider {
|
||||
* @see #updateSuggestedFromLatest()
|
||||
*/
|
||||
private void updateSuggestedFromUpstream() {
|
||||
Utils.debugLog(TAG, "Calculating suggested versions for all apps which specify an upstream version code.");
|
||||
Utils.debugLog(TAG, "Calculating suggested versions for all NON-INSTALLED apps which specify an upstream version code.");
|
||||
|
||||
Utils.Profiler profiler = new Utils.Profiler("UpdateSuggestedApks");
|
||||
final String apk = getApkTableName();
|
||||
final String app = getTableName();
|
||||
|
||||
@ -986,6 +987,7 @@ public class AppProvider extends FDroidProvider {
|
||||
" WHERE " + Cols.UPSTREAM_VERSION_CODE + " > 0 ";
|
||||
|
||||
LoggingQuery.execSQL(db(), updateSql);
|
||||
profiler.log("Done");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1029,7 +1031,7 @@ public class AppProvider extends FDroidProvider {
|
||||
" FROM " + InstalledAppTable.NAME + " AS installed " +
|
||||
" JOIN " + PackageTable.NAME + " AS pkg ON " +
|
||||
" (pkg." + PackageTable.Cols.ROW_ID + " = " + appTable + "." + Cols.PACKAGE_ID + " AND " +
|
||||
" installed." + InstalledAppTable.Cols.PACKAGE_NAME + " = pkg." + PackageTable.Cols.PACKAGE_NAME + ") " +
|
||||
" installed." + InstalledAppTable.Cols.PACKAGE_ID + " = pkg." + PackageTable.Cols.ROW_ID + ") " +
|
||||
")";
|
||||
|
||||
// Ideally, the check below would actually be written as:
|
||||
|
@ -182,7 +182,7 @@ class DBHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String CREATE_TABLE_INSTALLED_APP = "CREATE TABLE " + InstalledAppTable.NAME
|
||||
+ " ( "
|
||||
+ InstalledAppTable.Cols.PACKAGE_NAME + " TEXT NOT NULL PRIMARY KEY, "
|
||||
+ InstalledAppTable.Cols.PACKAGE_ID + " INT NOT NULL UNIQUE, "
|
||||
+ InstalledAppTable.Cols.VERSION_CODE + " INT NOT NULL, "
|
||||
+ InstalledAppTable.Cols.VERSION_NAME + " TEXT NOT NULL, "
|
||||
+ InstalledAppTable.Cols.APPLICATION_LABEL + " TEXT NOT NULL, "
|
||||
@ -192,7 +192,7 @@ class DBHelper extends SQLiteOpenHelper {
|
||||
+ InstalledAppTable.Cols.HASH + " TEXT NOT NULL"
|
||||
+ " );";
|
||||
|
||||
protected static final int DB_VERSION = 70;
|
||||
protected static final int DB_VERSION = 71;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@ -277,6 +277,28 @@ class DBHelper extends SQLiteOpenHelper {
|
||||
recalculatePreferredMetadata(db, oldVersion);
|
||||
addWhatsNewAndVideo(db, oldVersion);
|
||||
dropApkPrimaryKey(db, oldVersion);
|
||||
addIntegerPrimaryKeyToInstalledApps(db, oldVersion);
|
||||
}
|
||||
|
||||
private void addIntegerPrimaryKeyToInstalledApps(SQLiteDatabase db, int oldVersion) {
|
||||
if (oldVersion >= 71) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "Replacing primary key on installed app table with integer for performance.");
|
||||
|
||||
db.beginTransaction();
|
||||
try {
|
||||
if (tableExists(db, Schema.InstalledAppTable.NAME)) {
|
||||
db.execSQL("DROP TABLE " + Schema.InstalledAppTable.NAME);
|
||||
}
|
||||
|
||||
db.execSQL(CREATE_TABLE_INSTALLED_APP);
|
||||
ensureIndexes(db);
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
private void dropApkPrimaryKey(SQLiteDatabase db, int oldVersion) {
|
||||
@ -1061,9 +1083,11 @@ class DBHelper extends SQLiteOpenHelper {
|
||||
AppPrefsTable.Cols.IGNORE_THIS_UPDATE + ");");
|
||||
}
|
||||
|
||||
Utils.debugLog(TAG, "Ensuring indexes exist for " + InstalledAppTable.NAME);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS installedApp_appId_vercode on " + InstalledAppTable.NAME + " (" +
|
||||
InstalledAppTable.Cols.PACKAGE_NAME + ", " + InstalledAppTable.Cols.VERSION_CODE + ");");
|
||||
if (columnExists(db, InstalledAppTable.NAME, InstalledAppTable.Cols.PACKAGE_ID)) {
|
||||
Utils.debugLog(TAG, "Ensuring indexes exist for " + InstalledAppTable.NAME);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS installedApp_packageId_vercode on " + InstalledAppTable.NAME + " (" +
|
||||
InstalledAppTable.Cols.PACKAGE_ID + ", " + InstalledAppTable.Cols.VERSION_CODE + ");");
|
||||
}
|
||||
|
||||
Utils.debugLog(TAG, "Ensuring indexes exist for " + RepoTable.NAME);
|
||||
db.execSQL("CREATE INDEX IF NOT EXISTS repo_id_isSwap on " + RepoTable.NAME + " (" +
|
||||
|
@ -24,7 +24,7 @@ public class InstalledApp extends ValueObject {
|
||||
case Schema.InstalledAppTable.Cols._ID:
|
||||
id = cursor.getLong(i);
|
||||
break;
|
||||
case Schema.InstalledAppTable.Cols.PACKAGE_NAME:
|
||||
case Schema.InstalledAppTable.Cols.Package.NAME:
|
||||
packageName = cursor.getString(i);
|
||||
break;
|
||||
case Schema.InstalledAppTable.Cols.VERSION_CODE:
|
||||
|
@ -10,6 +10,7 @@ import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.fdroid.fdroid.Utils;
|
||||
@ -41,7 +42,7 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
cursor.moveToFirst();
|
||||
while (!cursor.isAfterLast()) {
|
||||
cachedInfo.put(
|
||||
cursor.getString(cursor.getColumnIndex(Cols.PACKAGE_NAME)),
|
||||
cursor.getString(cursor.getColumnIndex(Cols.Package.NAME)),
|
||||
cursor.getLong(cursor.getColumnIndex(Cols.LAST_UPDATE_TIME))
|
||||
);
|
||||
cursor.moveToNext();
|
||||
@ -136,7 +137,17 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
}
|
||||
|
||||
private QuerySelection queryApp(String packageName) {
|
||||
return new QuerySelection(Cols.PACKAGE_NAME + " = ?", new String[]{packageName});
|
||||
return new QuerySelection(Cols.Package.NAME + " = ?", new String[]{packageName});
|
||||
}
|
||||
|
||||
private QuerySelection queryAppSubQuery(String packageName) {
|
||||
String pkg = Schema.PackageTable.NAME;
|
||||
String subQuery = "(" +
|
||||
" SELECT " + pkg + "." + Schema.PackageTable.Cols.ROW_ID +
|
||||
" FROM " + pkg +
|
||||
" WHERE " + pkg + "." + Schema.PackageTable.Cols.PACKAGE_NAME + " = ?)";
|
||||
String query = Cols.PACKAGE_ID + " = " + subQuery;
|
||||
return new QuerySelection(query, new String[]{packageName});
|
||||
}
|
||||
|
||||
private QuerySelection querySearch(String query) {
|
||||
@ -144,6 +155,26 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
new String[]{"%" + query + "%"});
|
||||
}
|
||||
|
||||
private static class QueryBuilder extends org.fdroid.fdroid.data.QueryBuilder {
|
||||
@Override
|
||||
protected String getRequiredTables() {
|
||||
String pkg = Schema.PackageTable.NAME;
|
||||
String installed = InstalledAppTable.NAME;
|
||||
return installed + " JOIN " + pkg +
|
||||
" ON (" + pkg + "." + Schema.PackageTable.Cols.ROW_ID + " = " +
|
||||
installed + "." + Cols.PACKAGE_ID + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addField(String field) {
|
||||
if (TextUtils.equals(field, Cols.Package.NAME)) {
|
||||
appendField(Schema.PackageTable.Cols.PACKAGE_NAME, Schema.PackageTable.NAME, field);
|
||||
} else {
|
||||
appendField(field, InstalledAppTable.NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor query(Uri uri, String[] projection,
|
||||
String customSelection, String[] selectionArgs, String sortOrder) {
|
||||
@ -170,8 +201,15 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
Cursor cursor = db().query(getTableName(), projection,
|
||||
selection.getSelection(), selection.getArgs(), null, null, sortOrder);
|
||||
QueryBuilder query = new QueryBuilder();
|
||||
query.addFields(projection);
|
||||
if (projection.length == 0) {
|
||||
query.addField(Cols._ID);
|
||||
}
|
||||
query.addSelection(selection);
|
||||
query.addOrderBy(sortOrder);
|
||||
|
||||
Cursor cursor = db().rawQuery(query.toString(), selection.getArgs());
|
||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||
return cursor;
|
||||
}
|
||||
@ -184,7 +222,7 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
}
|
||||
|
||||
QuerySelection query = new QuerySelection(where, whereArgs);
|
||||
query = query.add(queryApp(uri.getLastPathSegment()));
|
||||
query = query.add(queryAppSubQuery(uri.getLastPathSegment()));
|
||||
|
||||
return db().delete(getTableName(), query.getSelection(), query.getArgs());
|
||||
}
|
||||
@ -196,9 +234,16 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
throw new UnsupportedOperationException("Insert not supported for " + uri + ".");
|
||||
}
|
||||
|
||||
if (values.containsKey(Cols.Package.NAME)) {
|
||||
String packageName = values.getAsString(Cols.Package.NAME);
|
||||
long packageId = PackageProvider.Helper.ensureExists(getContext(), packageName);
|
||||
values.remove(Cols.Package.NAME);
|
||||
values.put(Cols.PACKAGE_ID, packageId);
|
||||
}
|
||||
|
||||
verifyVersionNameNotNull(values);
|
||||
db().replaceOrThrow(getTableName(), null, values);
|
||||
return getAppUri(values.getAsString(Cols.PACKAGE_NAME));
|
||||
return getAppUri(values.getAsString(Cols.Package.NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -288,7 +288,7 @@ public class InstalledAppProviderService extends IntentService {
|
||||
static void insertAppIntoDb(Context context, PackageInfo packageInfo, String hashType, String hash) {
|
||||
Uri uri = InstalledAppProvider.getContentUri();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(InstalledAppTable.Cols.PACKAGE_NAME, packageInfo.packageName);
|
||||
contentValues.put(InstalledAppTable.Cols.Package.NAME, packageInfo.packageName);
|
||||
contentValues.put(InstalledAppTable.Cols.VERSION_CODE, packageInfo.versionCode);
|
||||
contentValues.put(InstalledAppTable.Cols.VERSION_NAME, packageInfo.versionName);
|
||||
contentValues.put(InstalledAppTable.Cols.APPLICATION_LABEL,
|
||||
|
@ -329,7 +329,7 @@ public interface Schema {
|
||||
|
||||
interface Cols {
|
||||
String _ID = "rowid as _id"; // Required for CursorLoaders
|
||||
String PACKAGE_NAME = "appId";
|
||||
String PACKAGE_ID = "packageId";
|
||||
String VERSION_CODE = "versionCode";
|
||||
String VERSION_NAME = "versionName";
|
||||
String APPLICATION_LABEL = "applicationLabel";
|
||||
@ -338,8 +338,12 @@ public interface Schema {
|
||||
String HASH_TYPE = "hashType";
|
||||
String HASH = "hash";
|
||||
|
||||
interface Package {
|
||||
String NAME = "packageName";
|
||||
}
|
||||
|
||||
String[] ALL = {
|
||||
_ID, PACKAGE_NAME, VERSION_CODE, VERSION_NAME, APPLICATION_LABEL,
|
||||
_ID, PACKAGE_ID, Package.NAME, VERSION_CODE, VERSION_NAME, APPLICATION_LABEL,
|
||||
SIGNATURE, LAST_UPDATE_TIME, HASH_TYPE, HASH,
|
||||
};
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ public class SelectAppsView extends ListView implements
|
||||
|
||||
private void toggleAppSelected(int position) {
|
||||
Cursor c = (Cursor) adapter.getItem(position);
|
||||
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.PACKAGE_NAME));
|
||||
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME));
|
||||
if (getState().hasSelectedPackage(packageName)) {
|
||||
getState().deselectPackage(packageName);
|
||||
adapter.updateCheckedIndicatorView(position, false);
|
||||
@ -176,7 +176,7 @@ public class SelectAppsView extends ListView implements
|
||||
|
||||
for (int i = 0; i < getCount(); i++) {
|
||||
Cursor c = (Cursor) getItemAtPosition(i);
|
||||
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.PACKAGE_NAME));
|
||||
String packageName = c.getString(c.getColumnIndex(InstalledAppTable.Cols.Package.NAME));
|
||||
getState().ensureFDroidSelected();
|
||||
for (String selected : getState().getAppsToSwap()) {
|
||||
if (TextUtils.equals(packageName, selected)) {
|
||||
@ -257,7 +257,7 @@ public class SelectAppsView extends ListView implements
|
||||
TextView labelView = (TextView) view.findViewById(R.id.application_label);
|
||||
ImageView iconView = (ImageView) view.findViewById(android.R.id.icon);
|
||||
|
||||
String packageName = cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.PACKAGE_NAME));
|
||||
String packageName = cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.Package.NAME));
|
||||
String appLabel = cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.APPLICATION_LABEL));
|
||||
|
||||
Drawable icon;
|
||||
|
@ -158,7 +158,7 @@ public class Assert {
|
||||
Uri uri = InstalledAppProvider.getAppUri(appId);
|
||||
|
||||
String[] projection = {
|
||||
InstalledAppTable.Cols.PACKAGE_NAME,
|
||||
InstalledAppTable.Cols.Package.NAME,
|
||||
InstalledAppTable.Cols.VERSION_CODE,
|
||||
InstalledAppTable.Cols.VERSION_NAME,
|
||||
InstalledAppTable.Cols.APPLICATION_LABEL,
|
||||
@ -171,7 +171,7 @@ public class Assert {
|
||||
|
||||
cursor.moveToFirst();
|
||||
|
||||
assertEquals(appId, cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.PACKAGE_NAME)));
|
||||
assertEquals(appId, cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.Package.NAME)));
|
||||
assertEquals(versionCode, cursor.getInt(cursor.getColumnIndex(InstalledAppTable.Cols.VERSION_CODE)));
|
||||
assertEquals(versionName, cursor.getString(cursor.getColumnIndex(InstalledAppTable.Cols.VERSION_NAME)));
|
||||
cursor.close();
|
||||
|
@ -37,7 +37,7 @@ public class InstalledAppProviderTest extends FDroidProviderTest {
|
||||
assertEquals(foundBefore.size(), 0);
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(Cols.PACKAGE_NAME, "org.example.test-app");
|
||||
values.put(Cols.Package.NAME, "org.example.test-app");
|
||||
values.put(Cols.APPLICATION_LABEL, "Test App");
|
||||
values.put(Cols.VERSION_CODE, 1021);
|
||||
values.put(Cols.VERSION_NAME, "Longhorn");
|
||||
@ -56,7 +56,7 @@ public class InstalledAppProviderTest extends FDroidProviderTest {
|
||||
assertEquals(cursor.getCount(), 1);
|
||||
|
||||
cursor.moveToFirst();
|
||||
assertEquals("org.example.test-app", cursor.getString(cursor.getColumnIndex(Cols.PACKAGE_NAME)));
|
||||
assertEquals("org.example.test-app", cursor.getString(cursor.getColumnIndex(Cols.Package.NAME)));
|
||||
assertEquals("Test App", cursor.getString(cursor.getColumnIndex(Cols.APPLICATION_LABEL)));
|
||||
assertEquals(1021, cursor.getInt(cursor.getColumnIndex(Cols.VERSION_CODE)));
|
||||
assertEquals("Longhorn", cursor.getString(cursor.getColumnIndex(Cols.VERSION_NAME)));
|
||||
@ -125,7 +125,7 @@ public class InstalledAppProviderTest extends FDroidProviderTest {
|
||||
Uri uri = InstalledAppProvider.getAppUri(packageName);
|
||||
|
||||
String[] projection = {
|
||||
Cols.PACKAGE_NAME,
|
||||
Cols.Package.NAME,
|
||||
Cols.LAST_UPDATE_TIME,
|
||||
};
|
||||
|
||||
@ -133,7 +133,7 @@ public class InstalledAppProviderTest extends FDroidProviderTest {
|
||||
assertNotNull(cursor);
|
||||
assertEquals("App \"" + packageName + "\" not installed", 1, cursor.getCount());
|
||||
cursor.moveToFirst();
|
||||
assertEquals(packageName, cursor.getString(cursor.getColumnIndex(Cols.PACKAGE_NAME)));
|
||||
assertEquals(packageName, cursor.getString(cursor.getColumnIndex(Cols.Package.NAME)));
|
||||
long lastUpdateTime = cursor.getLong(cursor.getColumnIndex(Cols.LAST_UPDATE_TIME));
|
||||
assertTrue(lastUpdateTime > 0);
|
||||
assertTrue(lastUpdateTime < System.currentTimeMillis());
|
||||
@ -170,7 +170,7 @@ public class InstalledAppProviderTest extends FDroidProviderTest {
|
||||
private ContentValues createContentValues(String appId, int versionCode, String versionNumber) {
|
||||
ContentValues values = new ContentValues(3);
|
||||
if (appId != null) {
|
||||
values.put(Cols.PACKAGE_NAME, appId);
|
||||
values.put(Cols.Package.NAME, appId);
|
||||
}
|
||||
values.put(Cols.APPLICATION_LABEL, "Mock app: " + appId);
|
||||
values.put(Cols.VERSION_CODE, versionCode);
|
||||
|
Loading…
x
Reference in New Issue
Block a user