diff options
author | David Storch <david.storch@10gen.com> | 2017-01-24 17:27:28 -0500 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2017-01-27 10:17:21 -0500 |
commit | c7c8e4151ddc745aea9c0f07ed1890518d00723d (patch) | |
tree | 83e7a47f812cd2bd7df5a3bf5242e99202bba8ac /src/mongo/db/bson | |
parent | 310ce16e32d0f2c110a0f8e2b11e0e0cbc1617ad (diff) | |
download | mongo-c7c8e4151ddc745aea9c0f07ed1890518d00723d.tar.gz |
SERVER-5580 track paths containing empty or single-element arrays as multikey
This is required in order for the planner to enforce correct
covering behavior.
Diffstat (limited to 'src/mongo/db/bson')
-rw-r--r-- | src/mongo/db/bson/dotted_path_support.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/bson/dotted_path_support.h | 2 | ||||
-rw-r--r-- | src/mongo/db/bson/dotted_path_support_test.cpp | 91 |
3 files changed, 94 insertions, 7 deletions
diff --git a/src/mongo/db/bson/dotted_path_support.cpp b/src/mongo/db/bson/dotted_path_support.cpp index 1a9fda88501..63a96686769 100644 --- a/src/mongo/db/bson/dotted_path_support.cpp +++ b/src/mongo/db/bson/dotted_path_support.cpp @@ -86,7 +86,6 @@ void _extractAllElementsAlongPath(const BSONObj& obj, depth + 1, arrayComponents); } else { - size_t nArrElems = 0; BSONObjIterator i(e.embeddedObject()); while (i.more()) { BSONElement e2 = i.next(); @@ -97,9 +96,8 @@ void _extractAllElementsAlongPath(const BSONObj& obj, expandArrayOnTrailingField, depth + 1, arrayComponents); - ++nArrElems; } - if (arrayComponents && nArrElems > 1) { + if (arrayComponents) { arrayComponents->insert(depth); } } @@ -109,13 +107,11 @@ void _extractAllElementsAlongPath(const BSONObj& obj, } } else { if (e.type() == Array && expandArrayOnTrailingField) { - size_t nArrElems = 0; BSONObjIterator i(e.embeddedObject()); while (i.more()) { elements.insert(i.next()); - ++nArrElems; } - if (arrayComponents && nArrElems > 1) { + if (arrayComponents) { arrayComponents->insert(depth); } } else { diff --git a/src/mongo/db/bson/dotted_path_support.h b/src/mongo/db/bson/dotted_path_support.h index c9c6676c75a..4d34901338c 100644 --- a/src/mongo/db/bson/dotted_path_support.h +++ b/src/mongo/db/bson/dotted_path_support.h @@ -83,7 +83,7 @@ BSONElement extractElementAtPathOrArrayAlongPath(const BSONObj& obj, const char* * and array elements. * * This function fills 'arrayComponents' with the positions (starting at 0) of 'path' corresponding - * to array values with multiple elements. + * to array values. * * Some examples: * diff --git a/src/mongo/db/bson/dotted_path_support_test.cpp b/src/mongo/db/bson/dotted_path_support_test.cpp index 06fa6dc2840..341750a9777 100644 --- a/src/mongo/db/bson/dotted_path_support_test.cpp +++ b/src/mongo/db/bson/dotted_path_support_test.cpp @@ -194,6 +194,19 @@ TEST(ExtractAllElementsAlongPath, NestedObjectWithEmptyArrayValue) { obj, "a.b", actualElements, expandArrayOnTrailingField, &actualArrayComponents); assertBSONElementSetsAreEqual(std::vector<BSONObj>{}, actualElements); + assertArrayComponentsAreEqual(std::set<size_t>{1U}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, NestedObjectWithEmptyArrayValueAndExpandParamIsFalse) { + BSONObj obj(fromjson("{a: {b: []}}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = false; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << BSONArray())}, actualElements); assertArrayComponentsAreEqual(std::set<size_t>{}, actualArrayComponents); } @@ -207,6 +220,19 @@ TEST(ExtractAllElementsAlongPath, NestedObjectWithSingletonArrayValue) { obj, "a.b", actualElements, expandArrayOnTrailingField, &actualArrayComponents); assertBSONElementSetsAreEqual({BSON("" << 1)}, actualElements); + assertArrayComponentsAreEqual(std::set<size_t>{1U}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, NestedObjectWithSingletonArrayValueAndExpandParamIsFalse) { + BSONObj obj(fromjson("{a: {b: {c: [3]}}}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = false; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b.c", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << BSON_ARRAY(3))}, actualElements); assertArrayComponentsAreEqual(std::set<size_t>{}, actualArrayComponents); } @@ -479,5 +505,70 @@ TEST(ExtractAllElementsAlongPath, DoesExpandArrayFoundAfterPositionalSpecificati assertArrayComponentsAreEqual({1U}, actualArrayComponents); } +TEST(ExtractAllElementsAlongPath, PositionalElementsNotConsideredArrayComponents) { + BSONObj obj(fromjson("{a: [{b: [1, 2]}]}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = true; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.0.b.1", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << 2)}, actualElements); + assertArrayComponentsAreEqual(std::set<size_t>{}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, TrailingArrayIsExpandedEvenIfPositional) { + BSONObj obj(fromjson("{a: {b: [0, [1, 2]]}}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = true; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b.1", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << 1), BSON("" << 2)}, actualElements); + assertArrayComponentsAreEqual({2U}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, PositionalTrailingArrayNotExpandedIfExpandParameterIsFalse) { + BSONObj obj(fromjson("{a: {b: [0, [1, 2]]}}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = false; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b.1", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << BSON_ARRAY(1 << 2))}, actualElements); + assertArrayComponentsAreEqual(std::set<size_t>{}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, MidPathEmptyArrayIsConsideredAnArrayComponent) { + BSONObj obj(fromjson("{a: [{b: []}]}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = true; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b.c", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual(std::vector<BSONObj>{}, actualElements); + assertArrayComponentsAreEqual({0U, 1U}, actualArrayComponents); +} + +TEST(ExtractAllElementsAlongPath, MidPathSingletonArrayIsConsideredAnArrayComponent) { + BSONObj obj(fromjson("{a: {b: [{c: 3}]}}")); + + BSONElementSet actualElements; + const bool expandArrayOnTrailingField = true; + std::set<size_t> actualArrayComponents; + dps::extractAllElementsAlongPath( + obj, "a.b.c", actualElements, expandArrayOnTrailingField, &actualArrayComponents); + + assertBSONElementSetsAreEqual({BSON("" << 3)}, actualElements); + assertArrayComponentsAreEqual({1U}, actualArrayComponents); +} + } // namespace } // namespace mongo |