Bug 897074 - Limit the number of tokens used in satchel's getAutoCompleteResults SQL queries. r=dolske

This commit is contained in:
Matthew Noorenberghe 2013-12-10 23:34:42 -08:00
Родитель b6058ad7d4
Коммит 5e796c882c
2 изменённых файлов: 50 добавлений и 2 удалений

Просмотреть файл

@ -98,6 +98,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "uuidService",
const DB_SCHEMA_VERSION = 4;
const DAY_IN_MS = 86400000; // 1 day in milliseconds
const MAX_SEARCH_TOKENS = 30;
const NOOP = function noop() {};
let supportsDeletedTable =
@ -969,7 +970,8 @@ this.FormHistory = {
// for each word, calculate word boundary weights for the SELECT clause and
// add word to the WHERE clause of the query
let tokenCalc = [];
for (let i = 0; i < searchTokens.length; i++) {
let searchTokenCount = Math.min(searchTokens.length, MAX_SEARCH_TOKENS);
for (let i = 0; i < searchTokenCount; i++) {
tokenCalc.push("(value LIKE :tokenBegin" + i + " ESCAPE '/') + " +
"(value LIKE :tokenBoundary" + i + " ESCAPE '/')");
where += "AND (value LIKE :tokenContains" + i + " ESCAPE '/') ";
@ -1021,7 +1023,8 @@ this.FormHistory = {
if (searchString.length >= 1)
stmt.params.valuePrefix = stmt.escapeStringForLIKE(searchString, "/") + "%";
if (searchString.length > 1) {
for (let i = 0; i < searchTokens.length; i++) {
let searchTokenCount = Math.min(searchTokens.length, MAX_SEARCH_TOKENS);
for (let i = 0; i < searchTokenCount; i++) {
let escapedToken = stmt.escapeStringForLIKE(searchTokens[i], "/");
stmt.params["tokenBegin" + i] = escapedToken + "%";
stmt.params["tokenBoundary" + i] = "% " + escapedToken + "%";

Просмотреть файл

@ -2,6 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var testnum = 0;
var fac;
var prefs;
@ -235,3 +237,46 @@ add_test(function test13() {
do_check_eq(results.getValueAt(1), "sync1a");
run_next_test();
});
add_test(function test_token_limit_DB() {
function test_token_limit_previousResult(previousResult) {
do_log_info("Check that the number of tokens used in a search is not capped to " +
"MAX_SEARCH_TOKENS when using a previousResult");
// This provide more accuracy since performance is less of an issue.
let changes = [ ];
// Search for a string where the first 30 tokens match the value above but the 31st does not
// when re-using a previous result.
fac.autoCompleteSearchAsync("field_token_cap",
"a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 .",
null, previousResult, {
onSearchCompletion : function(aResults) {
do_check_eq(aResults.matchCount, 0,
"All search tokens should be used with " +
"previous results");
run_next_test();
}
});
}
do_log_info("Check that the number of tokens used in a search is capped to MAX_SEARCH_TOKENS " +
"for performance when querying the DB");
let changes = [ ];
changes.push({ op : "add", fieldname: "field_token_cap",
// value with 36 unique tokens
value: "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 0",
timesUsed: 1, firstUsed: 0, lastUsed: 0 });
updateFormHistory(changes, () => {
// Search for a string where the first 30 tokens match the value above but the 31st does not
// (which would prevent the result from being returned if the 31st term was used).
fac.autoCompleteSearchAsync("field_token_cap",
"a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 .",
null, null, {
onSearchCompletion : function(aResults) {
do_check_eq(aResults.matchCount, 1,
"Only the first MAX_SEARCH_TOKENS tokens " +
"should be used for DB queries");
test_token_limit_previousResult(aResults);
}
});
});
});