pair<vector<BSONObj>, vector<BSONObj>> IndexAccessMethod::setDifference(const BSONObjSet& left, const BSONObjSet& right) { // Two iterators to traverse the two sets in sorted order. auto leftIt = left.begin(); auto rightIt = right.begin(); vector<BSONObj> onlyLeft; vector<BSONObj> onlyRight; while (leftIt != left.end() && rightIt != right.end()) { const int cmp = leftIt->woCompare(*rightIt); if (cmp == 0) { // 'leftIt' and 'rightIt' compare equal using woCompare(), but may not be identical, // which should result in an index change. if (!leftIt->binaryEqual(*rightIt)) { onlyLeft.push_back(*leftIt); onlyRight.push_back(*rightIt); } ++leftIt; ++rightIt; continue; } else if (cmp > 0) { onlyRight.push_back(*rightIt); ++rightIt; } else { onlyLeft.push_back(*leftIt); ++leftIt; } } // Add the rest of 'left' to 'onlyLeft', and the rest of 'right' to 'onlyRight', if any. onlyLeft.insert(onlyLeft.end(), leftIt, left.end()); onlyRight.insert(onlyRight.end(), rightIt, right.end()); return {std::move(onlyLeft), std::move(onlyRight)}; }
bool InMatchExpression::equivalent(const MatchExpression* other) const { if (matchType() != other->matchType()) { return false; } const InMatchExpression* realOther = static_cast<const InMatchExpression*>(other); if (path() != realOther->path()) { return false; } if (_hasNull != realOther->_hasNull) { return false; } if (_regexes.size() != realOther->_regexes.size()) { return false; } for (size_t i = 0; i < _regexes.size(); ++i) { if (!_regexes[i]->equivalent(realOther->_regexes[i].get())) { return false; } } if (!CollatorInterface::collatorsMatch(_collator, realOther->_collator)) { return false; } // We use an element-wise comparison to check equivalence of '_equalitySet'. Unfortunately, we // can't use BSONElementSet::operator==(), as it does not use the comparator object the set is // initialized with (and as such, it is not collation-aware). if (_equalitySet.size() != realOther->_equalitySet.size()) { return false; } auto thisEqIt = _equalitySet.begin(); auto otherEqIt = realOther->_equalitySet.begin(); for (; thisEqIt != _equalitySet.end(); ++thisEqIt, ++otherEqIt) { const bool considerFieldName = false; if (thisEqIt->woCompare(*otherEqIt, considerFieldName, _collator)) { return false; } } invariant(otherEqIt == realOther->_equalitySet.end()); return true; }