diff options
author | Jason Rassi <rassi@10gen.com> | 2014-10-15 17:48:10 -0400 |
---|---|---|
committer | Jason Rassi <rassi@10gen.com> | 2014-10-16 11:01:18 -0400 |
commit | 1579d801925ce9b92de088ca766483540cf6e741 (patch) | |
tree | da40f99a5a26b7c6b25dbe245bd1f92ad7bb6d21 /src/mongo/db/query | |
parent | 5f74509348939336562ab0db34afdf1b69e63c90 (diff) | |
download | mongo-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.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/query/query_planner_text_test.cpp | 11 |
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) { |