From 2bd70fc6b579552ba6bbe64286e5d44240361dd4 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Wed, 27 Sep 2017 15:37:09 +1000 Subject: [PATCH] Fixed query for known vulns. Used to work, then the default join from `fdroid_app` to `fdroid_apk` was removed for performance reasons. This adds the join back, but requires queries to explicitly opt in to the join if they require it. The specific query for known vulns is not a performance problem, because sqlite is able to narrow the result set quite substantially before requiring a join onto the fdroid_apk table anyway (e.g. by using the "installed app" table). --- .../org/fdroid/fdroid/data/AppProvider.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java b/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java index 30e77857b..c58d73faf 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java +++ b/app/src/main/java/org/fdroid/fdroid/data/AppProvider.java @@ -157,6 +157,7 @@ public class AppProvider extends FDroidProvider { protected static class AppQuerySelection extends QuerySelection { private boolean naturalJoinToInstalled; + private boolean naturalJoinApks; private boolean naturalJoinAntiFeatures; private boolean leftJoinPrefs; @@ -178,6 +179,10 @@ public class AppProvider extends FDroidProvider { return naturalJoinToInstalled; } + public boolean naturalJoinToApks() { + return naturalJoinApks; + } + public boolean naturalJoinAntiFeatures() { return naturalJoinAntiFeatures; } @@ -194,6 +199,17 @@ public class AppProvider extends FDroidProvider { return this; } + /** + * Note that this has large performance implications, so should only be used if you are already limiting + * the result set based on other, more drastic conditions first. + * See https://gitlab.com/fdroid/fdroidclient/issues/1143 for the investigation which identified these + * performance implications. + */ + public AppQuerySelection requireNaturalJoinApks() { + naturalJoinApks = true; + return this; + } + public AppQuerySelection requireNatrualJoinAntiFeatures() { naturalJoinAntiFeatures = true; return this; @@ -215,6 +231,10 @@ public class AppProvider extends FDroidProvider { bothWithJoin.requireNaturalInstalledTable(); } + if (this.naturalJoinToApks() || query.naturalJoinToApks()) { + bothWithJoin.requireNaturalJoinApks(); + } + if (this.leftJoinToPrefs() || query.leftJoinToPrefs()) { bothWithJoin.requireLeftJoinPrefs(); } @@ -232,6 +252,7 @@ public class AppProvider extends FDroidProvider { private boolean isSuggestedApkTableAdded; private boolean requiresInstalledTable; + private boolean requiresApkTable; private boolean requiresAntiFeatures; private boolean requiresLeftJoinToPrefs; private boolean countFieldAppended; @@ -263,6 +284,9 @@ public class AppProvider extends FDroidProvider { if (selection.naturalJoinToInstalled()) { naturalJoinToInstalledTable(); } + if (selection.naturalJoinToApks()) { + naturalJoinToApkTable(); + } if (selection.leftJoinToPrefs()) { leftJoinToPrefs(); } @@ -283,6 +307,17 @@ public class AppProvider extends FDroidProvider { } } + public void naturalJoinToApkTable() { + if (!requiresApkTable) { + join( + getApkTableName(), + getApkTableName(), + getApkTableName() + "." + ApkTable.Cols.APP_ID + " = " + getTableName() + "." + Cols.ROW_ID + ); + requiresApkTable = true; + } + } + public void leftJoinToPrefs() { if (!requiresLeftJoinToPrefs) { leftJoin( @@ -720,6 +755,7 @@ public class AppProvider extends FDroidProvider { return new AppQuerySelection(selection) .requireNaturalInstalledTable() + .requireNaturalJoinApks() .requireNatrualJoinAntiFeatures() .requireLeftJoinPrefs(); }