summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-10-26 11:20:12 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-10-26 15:07:07 -0400
commit1c91d1a2b789fef8be6427de81c35658ff30009d (patch)
treebaf49d48e66a16b774b41b7647f32cd9bbd2e212
parent75689917412c571427f12b7fe29a4dfa458d2df3 (diff)
downloadmongo-1c91d1a2b789fef8be6427de81c35658ff30009d.tar.gz
Revert "SERVER-20888: Defer $language check to FTSQuery::Parse"
This reverts commit 4c38ff13739e60d33d52b0c944d55249e7d9cc68.
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp12
-rw-r--r--src/mongo/db/fts/fts_matcher_test.cpp22
-rw-r--r--src/mongo/db/fts/fts_query.cpp17
-rw-r--r--src/mongo/db/fts/fts_query.h10
-rw-r--r--src/mongo/db/fts/fts_query_test.cpp51
-rw-r--r--src/mongo/db/matcher/expression_parser_text.cpp7
-rw-r--r--src/mongo/db/matcher/expression_parser_text_test.cpp7
-rw-r--r--src/mongo/db/query/stage_builder.cpp14
8 files changed, 84 insertions, 56 deletions
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index 8ee9f8b0e36..a3f5d29765e 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -457,11 +457,13 @@ public:
params.spec = fam->getSpec();
- params.query.parse(search,
- fam->getSpec().defaultLanguage().str().c_str(),
- fts::FTSQuery::caseSensitiveDefault,
- fts::FTSQuery::diacriticSensitiveDefault,
- fam->getSpec().getTextIndexVersion());
+ if (!params.query.parse(search,
+ fam->getSpec().defaultLanguage().str().c_str(),
+ fts::FTSQuery::caseSensitiveDefault,
+ fts::FTSQuery::diacriticSensitiveDefault,
+ fam->getSpec().getTextIndexVersion()).isOK()) {
+ return NULL;
+ }
return new TextStage(txn, params, workingSet, matcher);
} else if ("delete" == nodeName) {
diff --git a/src/mongo/db/fts/fts_matcher_test.cpp b/src/mongo/db/fts/fts_matcher_test.cpp
index 7694732e2e1..246510a9e70 100644
--- a/src/mongo/db/fts/fts_matcher_test.cpp
+++ b/src/mongo/db/fts/fts_matcher_test.cpp
@@ -38,7 +38,7 @@ namespace fts {
TEST(FTSMatcher, NegWild1) {
FTSQuery q;
- q.parse("foo -bar", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("foo -bar", "english", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
<< "text")))));
@@ -52,7 +52,7 @@ TEST(FTSMatcher, NegWild1) {
// Regression test for SERVER-11994.
TEST(FTSMatcher, NegWild2) {
FTSQuery q;
- q.parse("pizza -restaurant", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("pizza -restaurant", "english", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
<< "text")))));
@@ -65,7 +65,7 @@ TEST(FTSMatcher, NegWild2) {
TEST(FTSMatcher, Phrase1) {
FTSQuery q;
- q.parse("foo \"table top\"", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("foo \"table top\"", "english", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("$**"
<< "text")))));
@@ -87,7 +87,7 @@ TEST(FTSMatcher, Phrase1) {
TEST(FTSMatcher, Phrase2) {
FTSQuery q;
- q.parse("foo \"table top\"", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("foo \"table top\"", "english", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -98,7 +98,7 @@ TEST(FTSMatcher, Phrase2) {
// language.
TEST(FTSMatcher, ParsesUsingDocLanguage) {
FTSQuery q;
- q.parse("-glad", "none", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("-glad", "none", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -112,7 +112,7 @@ TEST(FTSMatcher, ParsesUsingDocLanguage) {
// Test the matcher does not filter out stop words from positive terms
TEST(FTSMatcher, MatcherDoesNotFilterStopWordsNeg) {
FTSQuery q;
- q.parse("-the", "none", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("-the", "none", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -124,7 +124,7 @@ TEST(FTSMatcher, MatcherDoesNotFilterStopWordsNeg) {
// Test the matcher does not filter out stop words from negative terms
TEST(FTSMatcher, MatcherDoesNotFilterStopWordsPos) {
FTSQuery q;
- q.parse("the", "none", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse("the", "none", false, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -137,7 +137,7 @@ TEST(FTSMatcher, MatcherDoesNotFilterStopWordsPos) {
// case-sensitive text query 'search'.
static bool docHasPositiveTermWithCase(const std::string& doc, const std::string& search) {
FTSQuery q;
- q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -164,7 +164,7 @@ TEST(FTSMatcher, HasPositiveTermCaseSensitive) {
// case-sensitive text query 'search'.
static bool docHasNegativeTermWithCase(const std::string& doc, const std::string& search) {
FTSQuery q;
- q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -191,7 +191,7 @@ TEST(FTSMatcher, HasNegativeTermCaseSensitive) {
// from case-sensitive text query 'search'.
static bool docPositivePhrasesMatchWithCase(const std::string& doc, const std::string& search) {
FTSQuery q;
- q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
@@ -214,7 +214,7 @@ TEST(FTSMatcher, PositivePhrasesMatchWithCase) {
// from case-sensitive text query 'search'.
static bool docNegativePhrasesMatchWithCase(const std::string& doc, const std::string& search) {
FTSQuery q;
- q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT_OK(q.parse(search, "english", true, false, TEXT_INDEX_VERSION_3));
FTSMatcher m(q,
FTSSpec(FTSSpec::fixSpec(BSON("key" << BSON("x"
<< "text")))));
diff --git a/src/mongo/db/fts/fts_query.cpp b/src/mongo/db/fts/fts_query.cpp
index 2dc9b222d3a..f162481066b 100644
--- a/src/mongo/db/fts/fts_query.cpp
+++ b/src/mongo/db/fts/fts_query.cpp
@@ -52,14 +52,15 @@ using std::vector;
const bool FTSQuery::caseSensitiveDefault = false;
const bool FTSQuery::diacriticSensitiveDefault = false;
-void FTSQuery::parse(const string& query,
- StringData language,
- bool caseSensitive,
- bool diacriticSensitive,
- TextIndexVersion textIndexVersion) {
+Status FTSQuery::parse(const string& query,
+ StringData language,
+ bool caseSensitive,
+ bool diacriticSensitive,
+ TextIndexVersion textIndexVersion) {
StatusWithFTSLanguage swl = FTSLanguage::make(language, textIndexVersion);
- uassertStatusOK(swl.getStatus());
-
+ if (!swl.getStatus().isOK()) {
+ return swl.getStatus();
+ }
_language = swl.getValue();
_caseSensitive = caseSensitive;
_diacriticSensitive = diacriticSensitive;
@@ -130,6 +131,8 @@ void FTSQuery::parse(const string& query,
_addTerms(tokenizer.get(), positiveTermSentence, false);
_addTerms(tokenizer.get(), negativeTermSentence, true);
+
+ return Status::OK();
}
void FTSQuery::_addTerms(FTSTokenizer* tokenizer, const string& sentence, bool negated) {
diff --git a/src/mongo/db/fts/fts_query.h b/src/mongo/db/fts/fts_query.h
index 3b7fbaa16f3..ea1882e4baf 100644
--- a/src/mongo/db/fts/fts_query.h
+++ b/src/mongo/db/fts/fts_query.h
@@ -50,11 +50,11 @@ public:
// version 1 (see fts_language.cpp for a list of language strings specific to version
// 1). Note that the diacritic sensitive option has no effect on FTS queries below index version
// 3.
- void parse(const std::string& query,
- StringData language,
- bool caseSensitive,
- bool diacriticSensitive,
- TextIndexVersion textIndexVersion);
+ Status parse(const std::string& query,
+ StringData language,
+ bool caseSensitive,
+ bool diacriticSensitive,
+ TextIndexVersion textIndexVersion);
const std::set<std::string>& getPositiveTerms() const {
return _positiveTerms;
diff --git a/src/mongo/db/fts/fts_query_test.cpp b/src/mongo/db/fts/fts_query_test.cpp
index dfdeeba68e7..bcf9e537142 100644
--- a/src/mongo/db/fts/fts_query_test.cpp
+++ b/src/mongo/db/fts/fts_query_test.cpp
@@ -37,7 +37,7 @@ namespace fts {
TEST(FTSQuery, Basic1) {
FTSQuery q;
- q.parse("this is fun", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("this is fun", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(false, q.getCaseSensitive());
ASSERT_EQUALS(1U, q.getPositiveTerms().size());
@@ -50,7 +50,7 @@ TEST(FTSQuery, Basic1) {
TEST(FTSQuery, ParsePunctuation) {
FTSQuery q;
- q.parse("hello.world", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("hello.world", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(false, q.getCaseSensitive());
ASSERT_EQUALS(2U, q.getPositiveTerms().size());
@@ -64,7 +64,7 @@ TEST(FTSQuery, ParsePunctuation) {
TEST(FTSQuery, Neg1) {
FTSQuery q;
- q.parse("this is -really fun", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("this is -really fun", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(1U, q.getPositiveTerms().size());
ASSERT_EQUALS("fun", *q.getPositiveTerms().begin());
@@ -75,7 +75,8 @@ TEST(FTSQuery, Neg1) {
TEST(FTSQuery, Phrase1) {
FTSQuery q;
- q.parse("doing a \"phrase test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("doing a \"phrase test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS(3U, q.getPositiveTerms().size());
ASSERT_EQUALS(0U, q.getNegatedTerms().size());
@@ -89,26 +90,29 @@ TEST(FTSQuery, Phrase1) {
TEST(FTSQuery, Phrase2) {
FTSQuery q;
- q.parse("doing a \"phrase-test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("doing a \"phrase-test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS(1U, q.getPositivePhr().size());
ASSERT_EQUALS("phrase-test", q.getPositivePhr()[0]);
}
TEST(FTSQuery, NegPhrase1) {
FTSQuery q;
- q.parse("doing a -\"phrase test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(
+ q.parse("doing a -\"phrase test\" for fun", "english", false, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS("fun||||||phrase test", q.debugString());
}
TEST(FTSQuery, CaseSensitiveOption) {
FTSQuery q;
- q.parse("this is fun", "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("this is fun", "english", true, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(true, q.getCaseSensitive());
}
TEST(FTSQuery, CaseSensitivePositiveTerms) {
FTSQuery q;
- q.parse("This is Positively fun", "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("This is Positively fun", "english", true, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(2U, q.getTermsForBounds().size());
ASSERT_EQUALS(1,
@@ -124,7 +128,8 @@ TEST(FTSQuery, CaseSensitivePositiveTerms) {
TEST(FTSQuery, CaseSensitiveNegativeTerms) {
FTSQuery q;
- q.parse("-This -is -Negatively -miserable", "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("-This -is -Negatively -miserable", "english", true, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS(0U, q.getPositiveTerms().size());
ASSERT_EQUALS(0U, q.getTermsForBounds().size());
@@ -137,7 +142,8 @@ TEST(FTSQuery, CaseSensitiveNegativeTerms) {
TEST(FTSQuery, CaseSensitivePositivePhrases) {
FTSQuery q;
- q.parse("doing a \"Phrase Test\" for fun", "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("doing a \"Phrase Test\" for fun", "english", true, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS(1U, q.getPositivePhr().size());
ASSERT_EQUALS(0U, q.getNegatedPhr().size());
@@ -146,7 +152,8 @@ TEST(FTSQuery, CaseSensitivePositivePhrases) {
TEST(FTSQuery, CaseSensitiveNegativePhrases) {
FTSQuery q;
- q.parse("doing a -\"Phrase Test\" for fun", "english", true, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q.parse("doing a -\"Phrase Test\" for fun", "english", true, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS(0U, q.getPositivePhr().size());
ASSERT_EQUALS(1U, q.getNegatedPhr().size());
@@ -155,15 +162,17 @@ TEST(FTSQuery, CaseSensitiveNegativePhrases) {
TEST(FTSQuery, Mix1) {
FTSQuery q;
- q.parse("\"industry\" -Melbourne -Physics", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(
+ q.parse("\"industry\" -Melbourne -Physics", "english", false, false, TEXT_INDEX_VERSION_3)
+ .isOK());
ASSERT_EQUALS("industri||melbourn|physic||industry||", q.debugString());
}
TEST(FTSQuery, NegPhrase2) {
FTSQuery q1, q2, q3;
- q1.parse("foo \"bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
- q2.parse("foo \"-bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
- q3.parse("foo \" -bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q1.parse("foo \"bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
+ ASSERT(q2.parse("foo \"-bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
+ ASSERT(q3.parse("foo \" -bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(2U, q1.getPositiveTerms().size());
ASSERT_EQUALS(2U, q2.getPositiveTerms().size());
@@ -184,9 +193,9 @@ TEST(FTSQuery, NegPhrase2) {
TEST(FTSQuery, NegPhrase3) {
FTSQuery q1, q2, q3;
- q1.parse("foo -\"bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
- q2.parse("foo -\"-bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
- q3.parse("foo -\" -bar\"", "english", false, false, TEXT_INDEX_VERSION_3);
+ ASSERT(q1.parse("foo -\"bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
+ ASSERT(q2.parse("foo -\"-bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
+ ASSERT(q3.parse("foo -\" -bar\"", "english", false, false, TEXT_INDEX_VERSION_3).isOK());
ASSERT_EQUALS(1U, q1.getPositiveTerms().size());
ASSERT_EQUALS(1U, q2.getPositiveTerms().size());
@@ -209,7 +218,7 @@ TEST(FTSQuery, NegPhrase3) {
// stemmer and stopword list.
TEST(FTSQuery, TextIndexVersion1LanguageEnglish) {
FTSQuery q;
- q.parse("the running", "english", false, false, TEXT_INDEX_VERSION_1);
+ ASSERT(q.parse("the running", "english", false, false, TEXT_INDEX_VERSION_1).isOK());
ASSERT_EQUALS(1U, q.getPositiveTerms().size());
ASSERT_EQUALS("run", *q.getPositiveTerms().begin());
ASSERT_EQUALS(0U, q.getNegatedTerms().size());
@@ -221,7 +230,7 @@ TEST(FTSQuery, TextIndexVersion1LanguageEnglish) {
// no stopword list.
TEST(FTSQuery, TextIndexVersion1LanguageEng) {
FTSQuery q;
- q.parse("the running", "eng", false, false, TEXT_INDEX_VERSION_1);
+ ASSERT(q.parse("the running", "eng", false, false, TEXT_INDEX_VERSION_1).isOK());
ASSERT_EQUALS(2U, q.getPositiveTerms().size());
ASSERT_EQUALS(1, std::count(q.getPositiveTerms().begin(), q.getPositiveTerms().end(), "the"));
ASSERT_EQUALS(1, std::count(q.getPositiveTerms().begin(), q.getPositiveTerms().end(), "run"));
@@ -234,7 +243,7 @@ TEST(FTSQuery, TextIndexVersion1LanguageEng) {
// and no stopword list will be used.
TEST(FTSQuery, TextIndexVersion1LanguageInvalid) {
FTSQuery q;
- q.parse("the running", "invalid", false, false, TEXT_INDEX_VERSION_1);
+ ASSERT(q.parse("the running", "invalid", false, false, TEXT_INDEX_VERSION_1).isOK());
ASSERT_EQUALS(2U, q.getPositiveTerms().size());
ASSERT_EQUALS(1, std::count(q.getPositiveTerms().begin(), q.getPositiveTerms().end(), "the"));
ASSERT_EQUALS(1,
diff --git a/src/mongo/db/matcher/expression_parser_text.cpp b/src/mongo/db/matcher/expression_parser_text.cpp
index d8dd49f4b85..6968dc6c0cb 100644
--- a/src/mongo/db/matcher/expression_parser_text.cpp
+++ b/src/mongo/db/matcher/expression_parser_text.cpp
@@ -60,8 +60,11 @@ StatusWithMatchExpression expressionParserTextCallbackReal(const BSONObj& queryO
"$language requires a string value");
}
language = languageElt.String();
- // NOTE: the language parameter is validated during FTSQuery::Parse when we have the index
- // spec and know which version of the index to use for the language list
+ Status status = fts::FTSLanguage::make(language, fts::TEXT_INDEX_VERSION_2).getStatus();
+ if (!status.isOK()) {
+ return StatusWithMatchExpression(ErrorCodes::BadValue,
+ "$language specifies unsupported language");
+ }
}
string query = queryObj["$search"].String();
diff --git a/src/mongo/db/matcher/expression_parser_text_test.cpp b/src/mongo/db/matcher/expression_parser_text_test.cpp
index 5aae8f0acd0..3d51604f7ef 100644
--- a/src/mongo/db/matcher/expression_parser_text_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_text_test.cpp
@@ -54,6 +54,13 @@ TEST(MatchExpressionParserText, Basic) {
ASSERT_EQUALS(textExp->getDiacriticSensitive(), fts::FTSQuery::diacriticSensitiveDefault);
}
+TEST(MatchExpressionParserText, LanguageError) {
+ BSONObj query = fromjson("{$text: {$search:\"awesome\", $language:\"spanglish\"}}");
+
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query);
+ ASSERT_FALSE(result.isOK());
+}
+
TEST(MatchExpressionParserText, CaseSensitiveTrue) {
BSONObj query = fromjson("{$text: {$search:\"awesome\", $caseSensitive: true}}");
diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp
index 5395294c1c6..b971c44288a 100644
--- a/src/mongo/db/query/stage_builder.cpp
+++ b/src/mongo/db/query/stage_builder.cpp
@@ -279,11 +279,15 @@ PlanStage* buildStages(OperationContext* txn,
const std::string& language =
("" == node->language ? fam->getSpec().defaultLanguage().str() : node->language);
- params.query.parse(node->query,
- language,
- node->caseSensitive,
- node->diacriticSensitive,
- fam->getSpec().getTextIndexVersion());
+ Status parseStatus = params.query.parse(node->query,
+ language,
+ node->caseSensitive,
+ node->diacriticSensitive,
+ fam->getSpec().getTextIndexVersion());
+ if (!parseStatus.isOK()) {
+ warning() << "Can't parse text search query";
+ return NULL;
+ }
return new TextStage(txn, params, ws, node->filter.get());
} else if (STAGE_SHARDING_FILTER == root->getType()) {