diff options
Diffstat (limited to 'src/mongo/db/matcher_covered.cpp')
| -rw-r--r-- | src/mongo/db/matcher_covered.cpp | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/mongo/db/matcher_covered.cpp b/src/mongo/db/matcher_covered.cpp new file mode 100644 index 00000000000..8fa0d7ce8a6 --- /dev/null +++ b/src/mongo/db/matcher_covered.cpp @@ -0,0 +1,122 @@ +// matcher_covered.cpp + +/* Matcher is our boolean expression evaluator for "where" clauses */ + +/** +* Copyright (C) 2008 10gen Inc. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU Affero General Public License, version 3, +* as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Affero General Public License for more details. +* +* You should have received a copy of the GNU Affero General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "pch.h" + +#include "mongo/db/matcher.h" + +#include "mongo/db/cursor.h" +#include "mongo/db/pdfile.h" +#include "mongo/db/queryutil.h" + +namespace mongo { + + CoveredIndexMatcher::CoveredIndexMatcher( const BSONObj &jsobj, + const BSONObj &indexKeyPattern ) : + _docMatcher( new Matcher( jsobj ) ), + _keyMatcher( *_docMatcher, indexKeyPattern ) { + init(); + } + + CoveredIndexMatcher::CoveredIndexMatcher( const CoveredIndexMatcher &prevClauseMatcher, + const shared_ptr<FieldRangeVector> &prevClauseFrv, + const BSONObj &nextClauseIndexKeyPattern ) : + _docMatcher( prevClauseMatcher._docMatcher ), + _keyMatcher( *_docMatcher, nextClauseIndexKeyPattern ), + _orDedupConstraints( prevClauseMatcher._orDedupConstraints ) { + if ( prevClauseFrv ) { + _orDedupConstraints.push_back( prevClauseFrv ); + } + init(); + } + + void CoveredIndexMatcher::init() { + _needRecord = + !_keyMatcher.keyMatch( *_docMatcher ) || + !_orDedupConstraints.empty(); + } + + bool CoveredIndexMatcher::matchesCurrent( Cursor * cursor , MatchDetails * details ) const { + // bool keyUsable = ! cursor->isMultiKey() && check for $orish like conditions in matcher SERVER-1264 + return matches( cursor->currKey() , cursor->currLoc() , details , + !cursor->indexKeyPattern().isEmpty() // unindexed cursor + && !cursor->isMultiKey() // multikey cursor + ); + } + + bool CoveredIndexMatcher::matches( const BSONObj& key, const DiskLoc& recLoc, + MatchDetails* details, bool keyUsable ) const { + + LOG(5) << "CoveredIndexMatcher::matches() " << key.toString() << ' ' << recLoc.toString() << ' ' << keyUsable << endl; + + dassert( key.isValid() ); + + if ( details ) + details->resetOutput(); + + if ( keyUsable ) { + if ( !_keyMatcher.matches(key, details ) ) { + return false; + } + bool needRecordForDetails = details && details->needRecord(); + if ( !_needRecord && !needRecordForDetails ) { + return true; + } + } + + if ( details ) + details->setLoadedRecord( true ); + + BSONObj obj = recLoc.obj(); + bool res = + _docMatcher->matches( obj, details ) && + !isOrClauseDup( obj ); + LOG(5) << "CoveredIndexMatcher _docMatcher->matches() returns " << res << endl; + return res; + } + + bool CoveredIndexMatcher::isOrClauseDup( const BSONObj &obj ) const { + for( vector<shared_ptr<FieldRangeVector> >::const_iterator i = _orDedupConstraints.begin(); + i != _orDedupConstraints.end(); ++i ) { + if ( (*i)->matches( obj ) ) { + // If a document matches a prior $or clause index range, generally it would have + // been returned while scanning that range and so is reported as a dup. + return true; + } + } + return false; + } + + string CoveredIndexMatcher::toString() const { + StringBuilder buf; + buf << "(CoveredIndexMatcher "; + + if ( _needRecord ) + buf << "needRecord "; + + buf << "keyMatcher: " << _keyMatcher.toString() << " "; + + if ( _docMatcher ) + buf << "docMatcher: " << _docMatcher->toString() << " "; + + buf << ")"; + return buf.str(); + } +} |
