diff options
author | Alberto Lerner <alerner@10gen.com> | 2013-07-05 10:35:20 -0400 |
---|---|---|
committer | Alberto Lerner <alerner@10gen.com> | 2013-07-05 10:35:20 -0400 |
commit | 1961a5d66cee7d9bc102cc2ff6f189c4c4306895 (patch) | |
tree | 5afc1c935a7bf81a0edc3ef0e0da32f150429858 /src/mongo/db/field_ref.cpp | |
parent | 5f949c19a26099320f1040e875b3841d4a362b26 (diff) | |
download | mongo-1961a5d66cee7d9bc102cc2ff6f189c4c4306895.tar.gz |
SERVER-7175 Support for catching conflicting mods in the update driver.
Diffstat (limited to 'src/mongo/db/field_ref.cpp')
-rw-r--r-- | src/mongo/db/field_ref.cpp | 88 |
1 files changed, 65 insertions, 23 deletions
diff --git a/src/mongo/db/field_ref.cpp b/src/mongo/db/field_ref.cpp index ab1cbc7046b..a23df8d3d7c 100644 --- a/src/mongo/db/field_ref.cpp +++ b/src/mongo/db/field_ref.cpp @@ -16,6 +16,8 @@ #include "mongo/db/field_ref.h" +#include <algorithm> // for min + #include "mongo/util/log.h" #include "mongo/util/assert_util.h" @@ -94,11 +96,37 @@ namespace mongo { } } - void FieldRef::clear() { - _size = 0; - _variable.clear(); - _fieldBase.reset(); - _replacements.clear(); + bool FieldRef::isPrefixOf( const FieldRef& other ) const { + // Can't be a prefix if the size is equal to or larger. + if ( _size >= other._size ) { + return false; + } + + // Empty FieldRef is not a prefix of anything. + if ( _size == 0 ) { + return false; + } + + size_t common = commonPrefixSize( other ); + return common == _size && other._size > common; + } + + size_t FieldRef::commonPrefixSize( const FieldRef& other ) const { + if (_size == 0 || other._size == 0) { + return 0; + } + + size_t maxPrefixSize = std::min( _size-1, other._size-1 ); + size_t prefixSize = 0; + + while ( prefixSize <= maxPrefixSize ) { + if ( getPart( prefixSize ) != other.getPart( prefixSize ) ) { + break; + } + prefixSize++; + } + + return prefixSize; } std::string FieldRef::dottedField( size_t offset ) const { @@ -117,27 +145,9 @@ namespace mongo { return res; } - bool FieldRef::isPrefixOf( const FieldRef& other ) const { - // Can't be a prefix if equal to or larger - if ( other._size <= _size ) - return false; - - for ( size_t i = 0; i < _size; i++ ) { - // Get parts - StringData part = getPart( i ); - StringData otherPart = other.getPart( i ); - - // If the parts are diff, can't be a prefix - if ( part != otherPart ) - return false; - } - return true; - } - bool FieldRef::equalsDottedField( const StringData& other ) const { StringData rest = other; - for ( size_t i = 0; i < _size; i++ ) { StringData part = getPart( i ); @@ -161,6 +171,34 @@ namespace mongo { return false; } + int FieldRef::compare(const FieldRef& other) const { + const size_t toCompare = std::min(_size, other._size); + for (size_t i = 0; i < toCompare; i++) { + if (getPart(i) == other.getPart(i)) { + continue; + } + return getPart(i) < other.getPart(i) ? -1 : 1; + } + + const size_t rest = _size - toCompare; + const size_t otherRest = other._size - toCompare; + if ((rest == 0) && (otherRest == 0)) { + return 0; + } + else if (rest < otherRest ) { + return -1; + } + else { + return 1; + } + } + + void FieldRef::clear() { + _size = 0; + _variable.clear(); + _fieldBase.reset(); + _replacements.clear(); + } size_t FieldRef::numReplaced() const { size_t res = 0; @@ -172,4 +210,8 @@ namespace mongo { return res; } + std::ostream& operator<<(std::ostream& stream, const FieldRef& field) { + return stream << field.dottedField(); + } + } // namespace mongo |