diff options
author | David Storch <david.storch@10gen.com> | 2016-03-04 14:26:06 -0500 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-03-10 14:28:10 -0500 |
commit | 36a86d9a57ce140ac8638f0a76bad9f0c5a2d2ba (patch) | |
tree | f3b6e32c1e42203590d9c6c296ab5c9359d04ed8 /src | |
parent | f380cfbff337cfd45ed51fa3f610f26ef5b2fc5e (diff) | |
download | mongo-36a86d9a57ce140ac8638f0a76bad9f0c5a2d2ba.tar.gz |
SERVER-22635 adjust CannotBackfillArray error checking to ensure array mods replicate properly
Previously we would return CannotBackfillArray whenever we had to
lengthen an array to index kMaxPaddingAllowed. Now we only return the
error if we actually have to backfill kMaxPaddingAllowed null
elements.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/ops/path_support.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/ops/path_support_test.cpp | 36 |
2 files changed, 40 insertions, 9 deletions
diff --git a/src/mongo/db/ops/path_support.cpp b/src/mongo/db/ops/path_support.cpp index 0523ef6acbb..e430c7d57cc 100644 --- a/src/mongo/db/ops/path_support.cpp +++ b/src/mongo/db/ops/path_support.cpp @@ -59,15 +59,16 @@ bool isNumeric(StringData str, size_t* num) { Status maybePadTo(mutablebson::Element* elemArray, size_t sizeRequired) { dassert(elemArray->getType() == Array); - if (sizeRequired > kMaxPaddingAllowed) { - return Status(ErrorCodes::CannotBackfillArray, - mongoutils::str::stream() << "can't backfill array to larger than " - << kMaxPaddingAllowed << " elements"); - } - size_t currSize = mutablebson::countChildren(*elemArray); if (sizeRequired > currSize) { size_t toPad = sizeRequired - currSize; + + if (toPad > kMaxPaddingAllowed) { + return Status(ErrorCodes::CannotBackfillArray, + mongoutils::str::stream() << "can't backfill more than " + << kMaxPaddingAllowed << " elements"); + } + for (size_t i = 0; i < toPad; i++) { Status status = elemArray->appendNull(""); if (!status.isOK()) { diff --git a/src/mongo/db/ops/path_support_test.cpp b/src/mongo/db/ops/path_support_test.cpp index 475c6552fc3..310a6eb2f72 100644 --- a/src/mongo/db/ops/path_support_test.cpp +++ b/src/mongo/db/ops/path_support_test.cpp @@ -455,9 +455,9 @@ TEST_F(ArrayDoc, ArrayPaddingNecessary) { } TEST_F(ArrayDoc, ExcessivePaddingRequested) { - // Try to create an array item beyond what we're allowed to pad. - string paddedField = stream() << "b." << mongo::pathsupport::kMaxPaddingAllowed + 1; - ; + // Try to create an array item beyond what we're allowed to pad. The index is two beyond the max + // padding since the array already has one element. + string paddedField = stream() << "b." << mongo::pathsupport::kMaxPaddingAllowed + 2; setField(paddedField); size_t idxFound; @@ -473,6 +473,36 @@ TEST_F(ArrayDoc, ExcessivePaddingRequested) { ASSERT_EQUALS(status.code(), ErrorCodes::CannotBackfillArray); } +TEST_F(ArrayDoc, ExcessivePaddingNotRequestedIfArrayAlreadyPadded) { + // We will try to set an array element whose index is 5 beyond the max padding. + string paddedField = stream() << "a." << mongo::pathsupport::kMaxPaddingAllowed + 5; + setField(paddedField); + + // Add 5 elements to the array. + for (size_t i = 0; i < 5; ++i) { + Element arrayA = doc().root().leftChild(); + ASSERT_EQ(arrayA.getFieldName(), "a"); + ASSERT_EQ(arrayA.getType(), mongo::Array); + arrayA.appendInt("", 1); + } + + size_t idxFound; + Element elemFound = root(); + ASSERT_OK(findLongestPrefix(field(), root(), &idxFound, &elemFound)); + ASSERT_TRUE(elemFound.ok()); + ASSERT_EQUALS(countChildren(elemFound), 5u); + + Element newElem = doc().makeElementInt("", 99); + ASSERT_TRUE(newElem.ok()); + + ASSERT_OK(createPathAt(field(), idxFound + 1, elemFound, newElem)); + + // Array should now have maxPadding + 6 elements, since the highest array index is maxPadding + + // 5. maxPadding of these elements are nulls adding as padding, 5 were appended at the + // beginning, and 1 was added by createPathAt(). + ASSERT_EQ(countChildren(doc().root().leftChild()), mongo::pathsupport::kMaxPaddingAllowed + 6); +} + TEST_F(ArrayDoc, NonNumericPathInArray) { setField("b.z"); |