summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-03-04 14:26:06 -0500
committerDavid Storch <david.storch@10gen.com>2016-03-10 14:28:10 -0500
commit36a86d9a57ce140ac8638f0a76bad9f0c5a2d2ba (patch)
treef3b6e32c1e42203590d9c6c296ab5c9359d04ed8
parentf380cfbff337cfd45ed51fa3f610f26ef5b2fc5e (diff)
downloadmongo-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.
-rw-r--r--src/mongo/db/ops/path_support.cpp13
-rw-r--r--src/mongo/db/ops/path_support_test.cpp36
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");