From 0d4005a1c755c4233bdf75d30a1b6ebc99856ec7 Mon Sep 17 00:00:00 2001 From: Fabrice Di Meglio Date: Thu, 6 Mar 2014 14:17:48 -0800 Subject: [PATCH] Fix bug #12910134 Implement Search into the Settings App - optimize MATCH query. Basically instead of doing 3 UNIONs, we are building a more clever MATCH query that can search on data_title OR data_summary OR data_keywords. - the consequence is that the generated SQL should be way more efficient to process and should also get the results faster. - last, as the generated SQL is shorter, it will be easier to understand and debug for Humans :-) Change-Id: I0f71740cae86b8c95ed88f9a5d13b8b4c860b1a9 --- src/com/android/settings/indexer/Index.java | 45 +++++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/indexer/Index.java b/src/com/android/settings/indexer/Index.java index 1a2eb480ce7..414c4d6b626 100644 --- a/src/com/android/settings/indexer/Index.java +++ b/src/com/android/settings/indexer/Index.java @@ -66,6 +66,12 @@ public class Index { IndexColumns.ICON }; + private static final String[] MATCH_COLUMNS = { + IndexColumns.DATA_TITLE, + IndexColumns.DATA_SUMMARY, + IndexColumns.DATA_KEYWORDS + }; + private static final String EMPTY = ""; private static final String NON_BREAKING_HYPHEN = "\u2011"; private static final String HYPHEN = "-"; @@ -96,22 +102,20 @@ public class Index { } public Cursor search(String query) { - return getReadableDatabase().rawQuery(buildSQL(query), null); + final String sql = buildSQL(query); + Log.d(LOG_TAG, "Query: " + sql); + return getReadableDatabase().rawQuery(sql, null); } private String buildSQL(String query) { StringBuilder sb = new StringBuilder(); - sb.append(buildSQLForColumn(query, IndexColumns.DATA_TITLE)); - sb.append(" UNION "); - sb.append(buildSQLForColumn(query, IndexColumns.DATA_SUMMARY)); - sb.append(" UNION "); - sb.append(buildSQLForColumn(query, IndexColumns.DATA_KEYWORDS)); + sb.append(buildSQLForColumn(query, MATCH_COLUMNS)); sb.append(" ORDER BY "); sb.append(IndexColumns.DATA_RANK); return sb.toString(); } - private String buildSQLForColumn(String query, String columnName) { + private String buildSQLForColumn(String query, String[] columnNames) { StringBuilder sb = new StringBuilder(); sb.append("SELECT "); for (int n = 0; n < SELECT_COLUMNS.length; n++) { @@ -123,15 +127,15 @@ public class Index { sb.append(" FROM "); sb.append(Tables.TABLE_PREFS_INDEX); sb.append(" WHERE "); - sb.append(buildWhereStringForColumn(query, columnName)); + sb.append(buildWhereStringForColumns(query, columnNames)); return sb.toString(); } - private String buildWhereStringForColumn(String query, String columnName) { - final StringBuilder sb = new StringBuilder(columnName); + private String buildWhereStringForColumns(String query, String[] columnNames) { + final StringBuilder sb = new StringBuilder(Tables.TABLE_PREFS_INDEX); sb.append(" MATCH "); - DatabaseUtils.appendEscapedSQLString(sb, query + "*"); + DatabaseUtils.appendEscapedSQLString(sb, buildMatchStringForColumns(query, columnNames)); sb.append(" AND "); sb.append(IndexColumns.LOCALE); sb.append(" = "); @@ -139,6 +143,21 @@ public class Index { return sb.toString(); } + private String buildMatchStringForColumns(String query, String[] columnNames) { + final String value = query + "*"; + StringBuilder sb = new StringBuilder(); + final int count = columnNames.length; + for (int n = 0; n < count; n++) { + sb.append(columnNames[n]); + sb.append(":"); + sb.append(value); + if (n < count - 1) { + sb.append(" OR "); + } + } + return sb.toString(); + } + public void addIndexableData(IndexableData data) { mDataToIndex.add(data); } @@ -271,9 +290,9 @@ public class Index { // Insert rows for the main PreferenceScreen node. Rewrite the data for removing // hyphens. inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName, - fragmentTitle, iconResId, rank, keywords, "\u2011", ""); + fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, EMPTY); inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName, - fragmentTitle, iconResId, rank, keywords, "\u2011", "-"); + fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, HYPHEN); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {