summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/query_planner_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/query_planner_test.cpp')
-rw-r--r--src/mongo/db/query/query_planner_test.cpp389
1 files changed, 0 insertions, 389 deletions
diff --git a/src/mongo/db/query/query_planner_test.cpp b/src/mongo/db/query/query_planner_test.cpp
index 417081795a6..58645fc9efc 100644
--- a/src/mongo/db/query/query_planner_test.cpp
+++ b/src/mongo/db/query/query_planner_test.cpp
@@ -5687,395 +5687,6 @@ TEST_F(QueryPlannerTest, SolutionSetStableWhenOrEnumerationLimitIsReached) {
"1}}}}}]}}");
}
-// Test that we enumerate the expected plans with the special parameter set. In this test we have
-// two branches of an $or, each with two possible indexed solutions.
-TEST_F(QueryPlannerTest, LockstepOrEnumerationSanityCheckTwoChildrenTwoIndexesEach) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
-
- runQueryAsCommand(
- fromjson("{find: 'testns', filter: {a: 1, $or: [{b: 1, c: 1}, {b: 2, c: 2}]}}"));
-
- assertNumSolutions(6U);
-
- assertSolutionExists(
- "{or: {nodes: [{fetch: {filter: {c: {$eq: 1} }, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}]}}");
- assertSolutionExists(
- "{or: {nodes: [{fetch: {filter: {b: {$eq: 1} }, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}]}}");
- assertSolutionExists(
- "{or: {nodes: [{fetch: {filter: {c: {$eq: 1} }, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}]}}");
- assertSolutionExists(
- "{or: {nodes: [{fetch: {filter: {b: {$eq: 1} }, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}]}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}, c: {$eq: 1}}, {b: {$eq: 2}, c: {$eq: 2}}]}, node: "
- "{ixscan: {pattern: {a: 1, b: 1}}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}, c: {$eq: 1}}, {b: {$eq: 2}, c: {$eq: 2}}]}, node: "
- "{ixscan: {pattern: {a: 1, c: 1}}}}}}}");
-}
-
-// Test that we enumerate the expected plans with the special parameter set. In this test we have
-// two branches of an $or, each with one possible indexed solution.
-TEST_F(QueryPlannerTest, LockstepOrEnumerationSanityCheckTwoChildrenOneIndexEach) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
-
- runQueryAsCommand(fromjson("{find: 'testns', filter: {a: 1, $or: [{b: 1}, {c: 2}]}}"));
-
- assertNumSolutions(3U);
-
- assertSolutionExists(
- "{fetch: {filter: null, node: {or: {nodes: [{ixscan: {pattern: {a: 1, b: 1}}}, {ixscan: "
- "{pattern: {a: 1, c: 1}}}]}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}}, {c: {$eq: 2}}]}, node: {ixscan: {pattern: {a: 1, "
- "b: 1}}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}}, {c: {$eq: 2}}]}, node: {ixscan: {pattern: {a: 1, "
- "c: 1}}}}}}}");
-}
-
-// Test that we enumerate the expected plans with the special parameter set. In this test we have
-// two branches of an $or, one with one possible indexed solution, the other with two possible
-// indexed solutions.
-TEST_F(QueryPlannerTest, LockstepOrEnumerationSanityCheckTwoChildrenDifferentNumSolutions) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
-
- runQueryAsCommand(fromjson("{find: 'testns', filter: {a: 1, $or: [{b: 1}, {b: 2, c: 2}]}}"));
-
- assertNumSolutions(4U);
-
- assertSolutionExists(
- "{fetch: {filter: null, node: {or: {nodes: [{ixscan: {pattern: {a: 1, b: 1}}}, {fetch: "
- "{filter: {c: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}]}}}}");
- assertSolutionExists(
- "{fetch: {filter: null, node: {or: {nodes: [{ixscan: {pattern: {a: 1, b: 1}}}, {fetch: "
- "{filter: {b: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}]}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}}, {b: {$eq: 2}, c: {$eq: 2}}]}, node: {ixscan: "
- "{pattern: {a: 1, b: 1}}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: [{b: {$eq: 1}}, {b: {$eq: 2}, c: {$eq: 2}}]}, node: {ixscan: "
- "{pattern: {a: 1, c: 1}}}}}}}");
-}
-
-// Test that the special parameter does in fact impact the order of enumeration. Here we rely on the
-// cap of number of or enumerations to prove that the plans we're interested in are enumerated
-// before we hit the limit.
-TEST_F(QueryPlannerTest, NormalOrEnumerationDoesNotPrioritizeLockstepIteration) {
- params.options = QueryPlannerParams::NO_TABLE_SCAN;
- ASSERT_EQ(internalQueryEnumerationMaxOrSolutions.load(), 10);
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
- addIndex(BSON("a" << 1 << "d" << 1));
-
- // For this query and the above indexes, each clause of the $or has three options to choose
- // from, for a total of 3 * 3 * 3 = 27 possible enumerations for just that $or sub-branch.
- runQueryAsCommand(
- fromjson("{find: 'testns', filter: {a: 1, $or: [{b: 1, c: 1, d: 1}, {b: 2, c: 2, d: 2}, "
- "{b: 3, c: 3, d: 3}]}}"));
-
- // The $or enumeration is limited to 10, and then we have three plans where just the {a: 1}
- // predicate is indexed.
- assertNumSolutions(13U);
-
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 1}, d: {$eq: 1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2}, d: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}} "
- "]}}");
- // Because we did not set the 'ENUMERATE_OR_CHILDREN_LOCKSTEP' flag, we don't expect this
- // solution to be generated. This is in contrast to the next test case.
- ASSERT_THROWS(
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 1}, c: {$eq: 1}}, node: {ixscan: {pattern: {a: 1, d: "
- "1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2}, c: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, d: "
- "1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: "
- "1}}}}} "
- "]}}"),
- unittest::TestAssertionFailureException);
-
- // We still expect to generate the solutions which don't index the $or.
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 1}, c: {$eq: 1}, d: {$eq: 1}}, "
- "{b: {$eq: 2}, c: {$eq: 2}, d: {$eq: 2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}} "
- "]}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}}");
-}
-
-TEST_F(QueryPlannerTest, LockstepOrEnumerationDoesPrioritizeLockstepIteration) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- ASSERT_EQ(internalQueryEnumerationMaxOrSolutions.load(), 10);
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
- addIndex(BSON("a" << 1 << "d" << 1));
-
- // For this query and the above indexes, each clause of the $or has three options to choose
- // from, for a total of 3 * 3 * 3 = 27 possible enumerations for just that $or sub-branch.
- runQueryAsCommand(
- fromjson("{find: 'testns', filter: {a: 1, $or: [{b: 1, c: 1, d: 1}, {b: 2, c: 2, d: 2}, "
- "{b: 3, c: 3, d: 3}]}}"));
-
- // The $or enumeration is limited to 10, and then we have three plans where just the {a: 1}
- // predicate is indexed.
- assertNumSolutions(13U);
-
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 1}, d: {$eq: 1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2}, d: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}} "
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 1}, d: {$eq: 1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2}, d: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}} "
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 1}, c: {$eq: 1}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2}, c: {$eq: 2}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}} "
- "]}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 1}, c: {$eq: 1}, d: {$eq: 1}}, "
- "{b: {$eq: 2}, c: {$eq: 2}, d: {$eq: 2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}} "
- "]}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}}");
-}
-
-TEST_F(QueryPlannerTest, LockstepOrEnumerationDoesPrioritizeLockstepIterationMixedChildren) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- ASSERT_EQ(internalQueryEnumerationMaxOrSolutions.load(), 10);
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
- addIndex(BSON("a" << 1 << "d" << 1));
- addIndex(BSON("a" << 1 << "e" << 1));
-
- // For this query and the above indexes, each clause of the $or has a varying number options to
- // choose from, for a total of 2 * 3 * 4 * 2 = 48 possible enumerations for just that $or
- // sub-branch.
- runQueryAsCommand(
- fromjson("{find: 'testns', filter: {"
- " a: 1,"
- " $or: ["
- " {b: 2.1, c: 2.1},"
- " {b: 3, c: 3, d: 3},"
- " {b: 4, c: 4, d: 4, e: 4},"
- " {b: 2.2, c: 2.2}"
- "]}}"));
-
- // The $or enumeration is limited to 10, and then we have four plans where just the {a: 1}
- // predicate is indexed.
- assertNumSolutions(14U);
-
- // Lockstep enumerations. Definitely expected.
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}"
- "]}}");
- // Everyone advances one more time, no longer lock step.
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}"
- "]}}");
- // Normal enumeration. Here we observe an interesting phenomena. Before we get into plan
- // enumeration, the query is parsed and "normalized". This process involves putting the query in
- // a canonical order, in part so that similar queries can be recognized as such for caching. In
- // this case, it orders the $or children by their respective number of children. So our original
- // query will be enumerated as if it were typed in this order:
- // {a: 1,
- // $or: [
- // {b: 2.1, c: 2.1},
- // {b: 2.2, c: 2.2},
- // {b: 3, c: 3, d: 3},
- // {b: 4, c: 4, d: 4, e: 4}
- // ]
- // }
- // Here are the exact plans:
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, d: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, d: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 3}, c: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, e: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, d: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, e: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, e: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, e: 1}}}}}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- "{fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- "{fetch: {filter: {c: {$eq: 3}, d: {$eq: 3}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- "{fetch: {filter: {b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}},"
- " node: {ixscan: {pattern: {a: 1, e: 1}}}}}"
- "]}}");
-
- // Now to the solutions which don't index the $or.
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 2.1}, c: {$eq: 2.1}}, "
- "{b: {$eq: 2.2}, c: {$eq: 2.2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}}, "
- "{b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}} "
- "]}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 2.1}, c: {$eq: 2.1}}, "
- "{b: {$eq: 2.2}, c: {$eq: 2.2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}}, "
- "{b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}} "
- "]}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 2.1}, c: {$eq: 2.1}}, "
- "{b: {$eq: 2.2}, c: {$eq: 2.2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}}, "
- "{b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}} "
- "]}, node: {ixscan: {pattern: {a: 1, d: 1}}}}}}");
- assertSolutionExists(
- "{fetch: {filter: {$or: ["
- "{b: {$eq: 2.1}, c: {$eq: 2.1}}, "
- "{b: {$eq: 2.2}, c: {$eq: 2.2}}, "
- "{b: {$eq: 3}, c: {$eq: 3}, d: {$eq: 3}}, "
- "{b: {$eq: 4}, c: {$eq: 4}, d: {$eq: 4}, e: {$eq: 4}} "
- "]}, node: {ixscan: {pattern: {a: 1, e: 1}}}}}}");
-}
-
-TEST_F(QueryPlannerTest, LockstepOrEnumerationApplysToEachOrInTree) {
- params.options =
- QueryPlannerParams::NO_TABLE_SCAN | QueryPlannerParams::ENUMERATE_OR_CHILDREN_LOCKSTEP;
- ASSERT_EQ(internalQueryEnumerationMaxOrSolutions.load(), 10);
- addIndex(BSON("a" << 1 << "b" << 1));
- addIndex(BSON("a" << 1 << "c" << 1));
- addIndex(BSON("a" << 1 << "x" << 1));
- addIndex(BSON("a" << 1 << "y" << 1));
-
- // For this query and the above indexes, each clause of the $or has 2 indexes to choose from,
- // for a total of 2 * 2 * 2 * 2 = 16 possible enumerations for just that $or sub-branch.
- runQueryAsCommand(
- fromjson("{find: 'testns', filter: {"
- " a: 1,"
- " $or: ["
- " {b: 2.1, c: 2.1},"
- " {b: 2.2, c: 2.2},"
- " {$and: ["
- " {unindexed: 'thisPredicateToEnsureNestedOrsAreNotCombined'},"
- " {$or: ["
- " {x: 3.0, y: 3.0},"
- " {x: 3.1, y: 3.1}"
- " ]}"
- " ]}"
- "]}}"));
-
- // The $or enumeration is limited to 10, and then we have 4 plans where just the {a: 1}
- // predicate is indexed.
- assertNumSolutions(14U);
-
- // Both lockstep enumerations should be present.
- assertSolutionExists(
- "{or: {nodes: ["
- " {fetch: {filter: {c: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- " {fetch: {filter: {c: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, b: 1}}}}}, "
- " {fetch: {"
- " filter: {unindexed: {$eq: 'thisPredicateToEnsureNestedOrsAreNotCombined'}},"
- " node: {"
- " or: {nodes: ["
- " {fetch: {filter: {y: {$eq: 3.0}}, node: {ixscan: {pattern: {a: 1, x: 1}}}}},"
- " {fetch: {filter: {y: {$eq: 3.1}}, node: {ixscan: {pattern: {a: 1, x: 1}}}}}"
- " ]}}"
- " }}"
- "]}}");
- assertSolutionExists(
- "{or: {nodes: ["
- " {fetch: {filter: {b: {$eq: 2.1}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- " {fetch: {filter: {b: {$eq: 2.2}}, node: {ixscan: {pattern: {a: 1, c: 1}}}}}, "
- " {fetch: {"
- " filter: {unindexed: {$eq: 'thisPredicateToEnsureNestedOrsAreNotCombined'}},"
- " node: {"
- " or: {nodes: ["
- " {fetch: {filter: {x: {$eq: 3.0}}, node: {ixscan: {pattern: {a: 1, y: 1}}}}},"
- " {fetch: {filter: {x: {$eq: 3.1}}, node: {ixscan: {pattern: {a: 1, y: 1}}}}}"
- " ]}}"
- " }}"
- "]}}");
-}
-
TEST_F(QueryPlannerTest, InvalidUtf8CodePointDoesNotLeadToInvalidIndexBoundsInvariantFailure) {
params.options &= ~QueryPlannerParams::INCLUDE_COLLSCAN;
addIndex(BSON("a" << 1));