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
This commit is contained in:
@@ -66,6 +66,12 @@ public class Index {
|
|||||||
IndexColumns.ICON
|
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 EMPTY = "";
|
||||||
private static final String NON_BREAKING_HYPHEN = "\u2011";
|
private static final String NON_BREAKING_HYPHEN = "\u2011";
|
||||||
private static final String HYPHEN = "-";
|
private static final String HYPHEN = "-";
|
||||||
@@ -96,22 +102,20 @@ public class Index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Cursor search(String query) {
|
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) {
|
private String buildSQL(String query) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(buildSQLForColumn(query, IndexColumns.DATA_TITLE));
|
sb.append(buildSQLForColumn(query, MATCH_COLUMNS));
|
||||||
sb.append(" UNION ");
|
|
||||||
sb.append(buildSQLForColumn(query, IndexColumns.DATA_SUMMARY));
|
|
||||||
sb.append(" UNION ");
|
|
||||||
sb.append(buildSQLForColumn(query, IndexColumns.DATA_KEYWORDS));
|
|
||||||
sb.append(" ORDER BY ");
|
sb.append(" ORDER BY ");
|
||||||
sb.append(IndexColumns.DATA_RANK);
|
sb.append(IndexColumns.DATA_RANK);
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildSQLForColumn(String query, String columnName) {
|
private String buildSQLForColumn(String query, String[] columnNames) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("SELECT ");
|
sb.append("SELECT ");
|
||||||
for (int n = 0; n < SELECT_COLUMNS.length; n++) {
|
for (int n = 0; n < SELECT_COLUMNS.length; n++) {
|
||||||
@@ -123,15 +127,15 @@ public class Index {
|
|||||||
sb.append(" FROM ");
|
sb.append(" FROM ");
|
||||||
sb.append(Tables.TABLE_PREFS_INDEX);
|
sb.append(Tables.TABLE_PREFS_INDEX);
|
||||||
sb.append(" WHERE ");
|
sb.append(" WHERE ");
|
||||||
sb.append(buildWhereStringForColumn(query, columnName));
|
sb.append(buildWhereStringForColumns(query, columnNames));
|
||||||
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildWhereStringForColumn(String query, String columnName) {
|
private String buildWhereStringForColumns(String query, String[] columnNames) {
|
||||||
final StringBuilder sb = new StringBuilder(columnName);
|
final StringBuilder sb = new StringBuilder(Tables.TABLE_PREFS_INDEX);
|
||||||
sb.append(" MATCH ");
|
sb.append(" MATCH ");
|
||||||
DatabaseUtils.appendEscapedSQLString(sb, query + "*");
|
DatabaseUtils.appendEscapedSQLString(sb, buildMatchStringForColumns(query, columnNames));
|
||||||
sb.append(" AND ");
|
sb.append(" AND ");
|
||||||
sb.append(IndexColumns.LOCALE);
|
sb.append(IndexColumns.LOCALE);
|
||||||
sb.append(" = ");
|
sb.append(" = ");
|
||||||
@@ -139,6 +143,21 @@ public class Index {
|
|||||||
return sb.toString();
|
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) {
|
public void addIndexableData(IndexableData data) {
|
||||||
mDataToIndex.add(data);
|
mDataToIndex.add(data);
|
||||||
}
|
}
|
||||||
@@ -271,9 +290,9 @@ public class Index {
|
|||||||
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
// Insert rows for the main PreferenceScreen node. Rewrite the data for removing
|
||||||
// hyphens.
|
// hyphens.
|
||||||
inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
|
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,
|
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
|
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
|
||||||
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
||||||
|
Reference in New Issue
Block a user