From 36a86d9a57ce140ac8638f0a76bad9f0c5a2d2ba Mon Sep 17 00:00:00 2001 From: David Storch Date: Fri, 4 Mar 2016 14:26:06 -0500 Subject: 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. --- src/mongo/db/ops/path_support.cpp | 13 ++++++------ src/mongo/db/ops/path_support_test.cpp | 36 +++++++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 9 deletions(-) (limited to 'src') 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"); -- cgit v1.2.1