summaryrefslogtreecommitdiff
path: root/src/mongo/db/query
diff options
context:
space:
mode:
authorJason Rassi <rassi@10gen.com>2014-10-15 17:48:10 -0400
committerJason Rassi <rassi@10gen.com>2014-10-16 11:01:18 -0400
commit1579d801925ce9b92de088ca766483540cf6e741 (patch)
treeda40f99a5a26b7c6b25dbe245bd1f92ad7bb6d21 /src/mongo/db/query
parent5f74509348939336562ab0db34afdf1b69e63c90 (diff)
downloadmongo-1579d801925ce9b92de088ca766483540cf6e741.tar.gz
SERVER-15639 Correctly handle >1 pred on same text index prefix field
Diffstat (limited to 'src/mongo/db/query')
-rw-r--r--src/mongo/db/query/planner_access.cpp6
-rw-r--r--src/mongo/db/query/query_planner_text_test.cpp11
2 files changed, 15 insertions, 2 deletions
diff --git a/src/mongo/db/query/planner_access.cpp b/src/mongo/db/query/planner_access.cpp
index 25ded0425c1..13d978f8d3d 100644
--- a/src/mongo/db/query/planner_access.cpp
+++ b/src/mongo/db/query/planner_access.cpp
@@ -408,11 +408,13 @@ namespace mongo {
MatchExpression* child = amExpr->getChild(curChild);
IndexTag* ixtag = static_cast<IndexTag*>(child->getTag());
invariant(NULL != ixtag);
- // Only want prefixes.
- if (ixtag->pos >= prefixEnd) {
+ // Skip this child if it's not part of a prefix, or if we've already assigned a
+ // predicate to this prefix position.
+ if (ixtag->pos >= prefixEnd || prefixExprs[ixtag->pos] != NULL) {
++curChild;
continue;
}
+ // prefixExprs takes ownership of 'child'.
prefixExprs[ixtag->pos] = child;
amExpr->getChildVector()->erase(amExpr->getChildVector()->begin() + curChild);
// Don't increment curChild.
diff --git a/src/mongo/db/query/query_planner_text_test.cpp b/src/mongo/db/query/query_planner_text_test.cpp
index 2925a2ff7da..13381e5165e 100644
--- a/src/mongo/db/query/query_planner_text_test.cpp
+++ b/src/mongo/db/query/query_planner_text_test.cpp
@@ -466,6 +466,17 @@ namespace {
assertSolutionExists("{text: {prefix: {a:3}, search: 'foo'}}");
}
+ // SERVER-15639: Test that predicates on index prefix fields which are not assigned to the index
+ // prefix are correctly included in the solution node filter.
+ TEST_F(QueryPlannerTest, TextInsideAndWithCompoundIndexAndMultiplePredsOnIndexPrefix) {
+ params.options = QueryPlannerParams::NO_TABLE_SCAN;
+ addIndex(BSON("a" << 1 << "_fts" << "text" << "_ftsx" << 1));
+ runQuery(fromjson("{$and: [{a: 1}, {a: 2}, {$text: {$search: 'foo'}}]}"));
+
+ assertNumSolutions(1U);
+ assertSolutionExists("{text: {prefix: {a: 1}, search: 'foo', filter: {a: 2}}}");
+ }
+
// SERVER-13039: Test that we don't generate invalid solutions when the TEXT node
// is buried beneath a logical node.
TEST_F(QueryPlannerTest, TextInsideOrBasic) {