diff options
author | Ian Boros <ian.boros@10gen.com> | 2018-07-31 13:32:15 -0400 |
---|---|---|
committer | Ian Boros <ian.boros@10gen.com> | 2018-08-31 10:59:42 -0400 |
commit | 7b42fb9ded007e90bd4961c46afa046af92675a8 (patch) | |
tree | ab8158bdb18fb1145cb51f25036d935949ee4181 /src/mongo/db/query/plan_cache_indexability_test.cpp | |
parent | dc076ee0d1c4b9463084b51694957dc63f8ba593 (diff) | |
download | mongo-7b42fb9ded007e90bd4961c46afa046af92675a8.tar.gz |
SERVER-35333 caching plans for allPaths indexes
Diffstat (limited to 'src/mongo/db/query/plan_cache_indexability_test.cpp')
-rw-r--r-- | src/mongo/db/query/plan_cache_indexability_test.cpp | 171 |
1 files changed, 132 insertions, 39 deletions
diff --git a/src/mongo/db/query/plan_cache_indexability_test.cpp b/src/mongo/db/query/plan_cache_indexability_test.cpp index bebec5ccdeb..bf409593859 100644 --- a/src/mongo/db/query/plan_cache_indexability_test.cpp +++ b/src/mongo/db/query/plan_cache_indexability_test.cpp @@ -55,11 +55,11 @@ std::unique_ptr<MatchExpression> parseMatchExpression(const BSONObj& obj, TEST(PlanCacheIndexabilityTest, SparseIndexSimple) { PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1), - false, // multikey - true, // sparse - false, // unique - "a_1", // name - nullptr, // filterExpr + false, // multikey + true, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name + nullptr, // filterExpr BSONObj())}); auto discriminators = state.getDiscriminators("a"); @@ -88,11 +88,11 @@ TEST(PlanCacheIndexabilityTest, SparseIndexSimple) { TEST(PlanCacheIndexabilityTest, SparseIndexCompound) { PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1 << "b" << 1), - false, // multikey - true, // sparse - false, // unique - "a_1_b_1", // name - nullptr, // filterExpr + false, // multikey + true, // sparse + false, // unique + IndexEntry::Identifier{"a_1_b_1"}, // name + nullptr, // filterExpr BSONObj())}); { @@ -128,10 +128,10 @@ TEST(PlanCacheIndexabilityTest, PartialIndexSimple) { std::unique_ptr<MatchExpression> filterExpr(parseMatchExpression(filterObj)); PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name filterExpr.get(), BSONObj())}); @@ -170,10 +170,10 @@ TEST(PlanCacheIndexabilityTest, PartialIndexAnd) { std::unique_ptr<MatchExpression> filterExpr(parseMatchExpression(filterObj)); PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name filterExpr.get(), BSONObj())}); @@ -224,17 +224,17 @@ TEST(PlanCacheIndexabilityTest, MultiplePartialIndexes) { PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name filterExpr1.get(), BSONObj()), IndexEntry(BSON("b" << 1), - false, // multikey - false, // sparse - false, // unique - "b_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"b_1"}, // name filterExpr2.get(), BSONObj())}); @@ -297,10 +297,10 @@ TEST(PlanCacheIndexabilityTest, MultiplePartialIndexes) { TEST(PlanCacheIndexabilityTest, IndexNeitherSparseNorPartial) { PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name nullptr, BSONObj())}); auto discriminators = state.getDiscriminators("a"); @@ -312,11 +312,11 @@ TEST(PlanCacheIndexabilityTest, IndexNeitherSparseNorPartial) { TEST(PlanCacheIndexabilityTest, DiscriminatorForCollationIndicatesWhenCollationsAreCompatible) { PlanCacheIndexabilityState state; IndexEntry entry(BSON("a" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1", // name - nullptr, // filterExpr + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1"}, // name + nullptr, // filterExpr BSONObj()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); entry.collator = &collator; @@ -393,10 +393,10 @@ TEST(PlanCacheIndexabilityTest, DiscriminatorForCollationIndicatesWhenCollations TEST(PlanCacheIndexabilityTest, CompoundIndexCollationDiscriminator) { PlanCacheIndexabilityState state; state.updateDiscriminators({IndexEntry(BSON("a" << 1 << "b" << 1), - false, // multikey - false, // sparse - false, // unique - "a_1_b_1", // name + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"a_1_b_1"}, // name nullptr, BSONObj())}); @@ -409,5 +409,98 @@ TEST(PlanCacheIndexabilityTest, CompoundIndexCollationDiscriminator) { ASSERT(discriminatorsB.find("a_1_b_1") != discriminatorsB.end()); } +TEST(PlanCacheIndexabilityTest, AllPathsDiscriminator) { + PlanCacheIndexabilityState state; + state.updateDiscriminators({IndexEntry(BSON("a.$**" << 1), + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"indexName"}, + nullptr, + BSONObj())}); + + const auto unindexedPathDiscriminators = state.buildAllPathsDiscriminators("notIndexed"); + ASSERT_EQ(0U, unindexedPathDiscriminators.size()); + + auto discriminatorsA = state.buildAllPathsDiscriminators("a"); + ASSERT_EQ(1U, discriminatorsA.size()); + ASSERT(discriminatorsA.find("indexName") != discriminatorsA.end()); + + const auto disc = discriminatorsA["indexName"]; + + ASSERT_TRUE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: 'abc'}")).get())); + + // Querying for object values isn't support by allPaths indexes. + ASSERT_FALSE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: {b: 1}}")).get())); + ASSERT_FALSE(disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: {}}")).get())); + ASSERT_FALSE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: {$lt: {}}}")).get())); + // Querying for array values isn't supported by allPaths indexes. + ASSERT_FALSE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: [1, 2, 3]}")).get())); + // Querying for null isn't supported by allPaths indexes. + ASSERT_FALSE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: null}")).get())); + + // Equality on empty array is supported. + ASSERT_TRUE(disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: []}")).get())); + // Inequality isn't. + ASSERT_FALSE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: {$gt: []}}")).get())); + + // Cases which use $in. + ASSERT_TRUE( + disc.isMatchCompatibleWithIndex(parseMatchExpression(fromjson("{a: {$in: []}}")).get())); + ASSERT_TRUE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, 2, 's']}}")).get())); + // Empty array inside the $in. + ASSERT_TRUE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, [], 's']}}")).get())); + + // Objects, non-empty arrays and null inside a $in. + ASSERT_FALSE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, {}, 's']}}")).get())); + ASSERT_FALSE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, {a: 1}, 's']}}")).get())); + ASSERT_FALSE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, [1,2,3], 's']}}")).get())); + ASSERT_FALSE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: {$in: [1, 2, null]}}")).get())); +} + +TEST(PlanCacheIndexabilityTest, AllPathsWithCollationDiscriminator) { + PlanCacheIndexabilityState state; + IndexEntry entry(BSON("a.$**" << 1), + false, // multikey + false, // sparse + false, // unique + IndexEntry::Identifier{"indexName"}, + nullptr, + BSONObj()); + CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); + entry.collator = &collator; + state.updateDiscriminators({entry}); + + const auto unindexedPathDiscriminators = state.buildAllPathsDiscriminators("notIndexed"); + ASSERT_EQ(0U, unindexedPathDiscriminators.size()); + + auto discriminatorsA = state.buildAllPathsDiscriminators("a"); + ASSERT_EQ(1U, discriminatorsA.size()); + ASSERT(discriminatorsA.find("indexName") != discriminatorsA.end()); + + const auto disc = discriminatorsA["indexName"]; + + // Match expression which uses the simple collation isn't compatible. + ASSERT_FALSE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: \"hello world\"}"), nullptr).get())); + // Match expression which uses the same collation as the index is. + ASSERT_TRUE(disc.isMatchCompatibleWithIndex( + parseMatchExpression(fromjson("{a: \"hello world\"}"), &collator).get())); +} + +// TODO SERVER-35336: Update this test to use a partial $** index, and be sure indexability +// discriminators also work for partial indices. } // namespace } // namespace mongo |