diff options
Diffstat (limited to 'src/mongo/db/field_ref_set.cpp')
-rw-r--r-- | src/mongo/db/field_ref_set.cpp | 208 |
1 files changed, 102 insertions, 106 deletions
diff --git a/src/mongo/db/field_ref_set.cpp b/src/mongo/db/field_ref_set.cpp index efc49f2dd1d..4b46cf50b2b 100644 --- a/src/mongo/db/field_ref_set.cpp +++ b/src/mongo/db/field_ref_set.cpp @@ -33,129 +33,125 @@ namespace mongo { - using std::vector; - using std::string; - namespace str = mongoutils::str; - - namespace { - - // For legacy purposes, we must handle empty fieldnames, which FieldRef clearly - // prohibits. It is preferrable to have FieldRef keep that constraint and relax it here - // -- stricly in update code. The rationale is that, if we want to ban data with no - // field names, we must allow that data to be updated. - StringData safeFirstPart(const FieldRef* fieldRef) { - if (fieldRef->numParts() == 0) { - return StringData(); - } - else { - return fieldRef->getPart(0); - } - } - +using std::vector; +using std::string; +namespace str = mongoutils::str; + +namespace { + +// For legacy purposes, we must handle empty fieldnames, which FieldRef clearly +// prohibits. It is preferrable to have FieldRef keep that constraint and relax it here +// -- stricly in update code. The rationale is that, if we want to ban data with no +// field names, we must allow that data to be updated. +StringData safeFirstPart(const FieldRef* fieldRef) { + if (fieldRef->numParts() == 0) { + return StringData(); + } else { + return fieldRef->getPart(0); } +} +} - bool FieldRefSet::FieldRefPtrLessThan::operator()(const FieldRef* l, const FieldRef* r) const { - return *l < *r; - } +bool FieldRefSet::FieldRefPtrLessThan::operator()(const FieldRef* l, const FieldRef* r) const { + return *l < *r; +} - FieldRefSet::FieldRefSet() { - } +FieldRefSet::FieldRefSet() {} - FieldRefSet::FieldRefSet(const vector<FieldRef*>& paths) { - fillFrom(paths); - } +FieldRefSet::FieldRefSet(const vector<FieldRef*>& paths) { + fillFrom(paths); +} - bool FieldRefSet::findConflicts(const FieldRef* toCheck, FieldRefSet* conflicts) const { - bool foundConflict = false; +bool FieldRefSet::findConflicts(const FieldRef* toCheck, FieldRefSet* conflicts) const { + bool foundConflict = false; - // If the set is empty, there is no work to do. - if (_fieldSet.empty()) - return foundConflict; + // If the set is empty, there is no work to do. + if (_fieldSet.empty()) + return foundConflict; - StringData prefixStr = safeFirstPart(toCheck); - FieldRef prefixField(prefixStr); + StringData prefixStr = safeFirstPart(toCheck); + FieldRef prefixField(prefixStr); - FieldSet::iterator it = _fieldSet.lower_bound(&prefixField); - // Now, iterate over all the present fields in the set that have the same prefix. + FieldSet::iterator it = _fieldSet.lower_bound(&prefixField); + // Now, iterate over all the present fields in the set that have the same prefix. - while (it != _fieldSet.end() && safeFirstPart(*it) == prefixStr) { - size_t common = (*it)->commonPrefixSize(*toCheck); - if ((*it)->numParts() == common || toCheck->numParts() == common) { - if (!conflicts) - return true; + while (it != _fieldSet.end() && safeFirstPart(*it) == prefixStr) { + size_t common = (*it)->commonPrefixSize(*toCheck); + if ((*it)->numParts() == common || toCheck->numParts() == common) { + if (!conflicts) + return true; - conflicts->_fieldSet.insert(*it); - foundConflict = true; - } - ++it; + conflicts->_fieldSet.insert(*it); + foundConflict = true; } - - return foundConflict; + ++it; } - void FieldRefSet::keepShortest(const FieldRef* toInsert) { - const FieldRef* conflict; - if ( !insert(toInsert, &conflict) && (toInsert->numParts() < (conflict->numParts()))) { - _fieldSet.erase(conflict); - keepShortest(toInsert); - } - } + return foundConflict; +} - void FieldRefSet::fillFrom(const std::vector<FieldRef*>& fields) { - dassert(_fieldSet.empty()); - _fieldSet.insert(fields.begin(), fields.end()); +void FieldRefSet::keepShortest(const FieldRef* toInsert) { + const FieldRef* conflict; + if (!insert(toInsert, &conflict) && (toInsert->numParts() < (conflict->numParts()))) { + _fieldSet.erase(conflict); + keepShortest(toInsert); } - - bool FieldRefSet::insert(const FieldRef* toInsert, const FieldRef** conflict) { - - // We can determine if two fields conflict by checking their common prefix. - // - // If each field is exactly of the size of the common prefix, this means the fields are - // the same. If one of the fields is greater than the common prefix and the other - // isn't, the latter is a prefix of the former. And vice-versa. - // - // Example: - // - // inserted > | a a.c - // exiting v | (0) (+1) - // ----------------|------------------------ - // a (0) | equal prefix < - // a.b (+1) | prefix ^ * - // - // * Disjoint sub-trees - - // At each insertion, we only need to bother checking the fields in the set that have - // at least some common prefix with the 'toInsert' field. - StringData prefixStr = safeFirstPart(toInsert); - FieldRef prefixField(prefixStr); - FieldSet::iterator it = _fieldSet.lower_bound(&prefixField); - - // Now, iterate over all the present fields in the set that have the same prefix. - while (it != _fieldSet.end() && safeFirstPart(*it) == prefixStr) { - size_t common = (*it)->commonPrefixSize(*toInsert); - if ((*it)->numParts() == common || toInsert->numParts() == common) { - *conflict = *it; - return false; - } - ++it; +} + +void FieldRefSet::fillFrom(const std::vector<FieldRef*>& fields) { + dassert(_fieldSet.empty()); + _fieldSet.insert(fields.begin(), fields.end()); +} + +bool FieldRefSet::insert(const FieldRef* toInsert, const FieldRef** conflict) { + // We can determine if two fields conflict by checking their common prefix. + // + // If each field is exactly of the size of the common prefix, this means the fields are + // the same. If one of the fields is greater than the common prefix and the other + // isn't, the latter is a prefix of the former. And vice-versa. + // + // Example: + // + // inserted > | a a.c + // exiting v | (0) (+1) + // ----------------|------------------------ + // a (0) | equal prefix < + // a.b (+1) | prefix ^ * + // + // * Disjoint sub-trees + + // At each insertion, we only need to bother checking the fields in the set that have + // at least some common prefix with the 'toInsert' field. + StringData prefixStr = safeFirstPart(toInsert); + FieldRef prefixField(prefixStr); + FieldSet::iterator it = _fieldSet.lower_bound(&prefixField); + + // Now, iterate over all the present fields in the set that have the same prefix. + while (it != _fieldSet.end() && safeFirstPart(*it) == prefixStr) { + size_t common = (*it)->commonPrefixSize(*toInsert); + if ((*it)->numParts() == common || toInsert->numParts() == common) { + *conflict = *it; + return false; } - - _fieldSet.insert(it, toInsert); - *conflict = NULL; - return true; + ++it; } - const std::string FieldRefSet::toString() const { - str::stream res; - res << "Fields:[ "; - FieldRefSet::const_iterator where = _fieldSet.begin(); - const FieldRefSet::const_iterator end = _fieldSet.end(); - for( ; where != end; ++where ) { - const FieldRef& current = **where; - res << current.dottedField() << ","; - } - res << "]"; - return res; + _fieldSet.insert(it, toInsert); + *conflict = NULL; + return true; +} + +const std::string FieldRefSet::toString() const { + str::stream res; + res << "Fields:[ "; + FieldRefSet::const_iterator where = _fieldSet.begin(); + const FieldRefSet::const_iterator end = _fieldSet.end(); + for (; where != end; ++where) { + const FieldRef& current = **where; + res << current.dottedField() << ","; } + res << "]"; + return res; +} -} // namespace mongo +} // namespace mongo |