diff options
author | Justin Seyster <justin.seyster@mongodb.com> | 2017-07-06 12:26:13 -0400 |
---|---|---|
committer | Justin Seyster <justin.seyster@mongodb.com> | 2017-07-06 12:26:13 -0400 |
commit | 3ea2d70f0260b1ec6ec8c60d42d6a6669a802ef2 (patch) | |
tree | 74726f49c4e14ce5cce1b69c56b2157c3f033bc9 /src/mongo/db/update/path_support.cpp | |
parent | 72e31a462ab80abfdfc36fb76443ec48fc3f65c9 (diff) | |
download | mongo-3ea2d70f0260b1ec6ec8c60d42d6a6669a802ef2.tar.gz |
SERVER-29762 Look up arrays by index during update.
This patch moves getPositionalPathSpecification() from its location in
document_path_support.h to stringutils.h, where it is renamed to
parseUnsignedBase10Integer(). This function should now be what all
code uses that needs to use a path component to look up an element in
an array.
There are two problems with trying to look up an array element by
string, which this patch addresses (for one particular case). The
first is that it will fail if the path component has leading zeros
(e.g. "a.01.b").
The second problem is that mutable BSON does not maintain the
invariant that array elements have their index as their field name
throughout the entire lifetime of the mutable document. Array lookups
by string fail during the times that this invariant does not hold
(notably, after a mutable array has been extended in length).
Diffstat (limited to 'src/mongo/db/update/path_support.cpp')
-rw-r--r-- | src/mongo/db/update/path_support.cpp | 27 |
1 files changed, 8 insertions, 19 deletions
diff --git a/src/mongo/db/update/path_support.cpp b/src/mongo/db/update/path_support.cpp index 73a7b5528db..4f33006444b 100644 --- a/src/mongo/db/update/path_support.cpp +++ b/src/mongo/db/update/path_support.cpp @@ -34,6 +34,7 @@ #include "mongo/bson/mutable/element.h" #include "mongo/util/assert_util.h" #include "mongo/util/mongoutils/str.h" +#include "mongo/util/stringutils.h" namespace mongo { namespace pathsupport { @@ -69,19 +70,6 @@ Status maybePadTo(mutablebson::Element* elemArray, size_t sizeRequired) { } // unnamed namespace -bool isNumericPathComponent(StringData str, size_t* num) { - size_t res = 0; - for (size_t i = 0; i < str.size(); ++i) { - if (str[i] < '0' || str[i] > '9') { - return false; - } else { - res = res * 10 + (str[i] - '0'); - } - } - *num = res; - return true; -} - Status findLongestPrefix(const FieldRef& prefix, mutablebson::Element root, size_t* idxFound, @@ -97,7 +85,7 @@ Status findLongestPrefix(const FieldRef& prefix, mutablebson::Element curr = root; mutablebson::Element prev = root; size_t i = 0; - size_t numericPart = 0; + boost::optional<size_t> numericPart; bool viable = true; for (; i < prefixSize; i++) { // If prefix wants to reach 'curr' by applying a non-numeric index to an array @@ -111,10 +99,11 @@ Status findLongestPrefix(const FieldRef& prefix, break; case Array: - if (!isNumericPathComponent(prefixPart, &numericPart)) { + numericPart = parseUnsignedBase10Integer(prefixPart); + if (!numericPart) { viable = false; } else { - curr = prev[numericPart]; + curr = prev[*numericPart]; } break; @@ -184,8 +173,8 @@ StatusWith<mutablebson::Element> createPathAt(const FieldRef& prefix, size_t i = idxFound; bool inArray = false; if (elemFound.getType() == mongo::Array) { - size_t newIdx = 0; - if (!isNumericPathComponent(prefix.getPart(idxFound), &newIdx)) { + boost::optional<size_t> newIdx = parseUnsignedBase10Integer(prefix.getPart(idxFound)); + if (!newIdx) { return Status(ErrorCodes::PathNotViable, str::stream() << "Cannot create field '" << prefix.getPart(idxFound) << "' in element {" @@ -193,7 +182,7 @@ StatusWith<mutablebson::Element> createPathAt(const FieldRef& prefix, << "}"); } - status = maybePadTo(&elemFound, newIdx); + status = maybePadTo(&elemFound, *newIdx); if (!status.isOK()) { return status; } |