00001
00002
00003
00004
00021 #pragma once
00022
00023 #include "jsobj.h"
00024 #include <pcrecpp.h>
00025
00026 namespace mongo {
00027
00028 class Cursor;
00029 class CoveredIndexMatcher;
00030 class Matcher;
00031 class FieldRangeVector;
00032
00033 class RegexMatcher {
00034 public:
00035 const char *fieldName;
00036 const char *regex;
00037 const char *flags;
00038 string prefix;
00039 shared_ptr< pcrecpp::RE > re;
00040 bool isNot;
00041 RegexMatcher() : isNot() {}
00042 };
00043
00044 struct element_lt {
00045 bool operator()(const BSONElement& l, const BSONElement& r) const {
00046 int x = (int) l.canonicalType() - (int) r.canonicalType();
00047 if ( x < 0 ) return true;
00048 else if ( x > 0 ) return false;
00049 return compareElementValues(l,r) < 0;
00050 }
00051 };
00052
00053
00054 class ElementMatcher {
00055 public:
00056
00057 ElementMatcher() {
00058 }
00059
00060 ElementMatcher( BSONElement _e , int _op, bool _isNot );
00061
00062 ElementMatcher( BSONElement _e , int _op , const BSONObj& array, bool _isNot );
00063
00064 ~ElementMatcher() { }
00065
00066 BSONElement toMatch;
00067 int compareOp;
00068 bool isNot;
00069 shared_ptr< set<BSONElement,element_lt> > myset;
00070 shared_ptr< vector<RegexMatcher> > myregex;
00071
00072
00073 int mod;
00074 int modm;
00075 BSONType type;
00076
00077 shared_ptr<Matcher> subMatcher;
00078 bool subMatcherOnPrimitives ;
00079
00080 vector< shared_ptr<Matcher> > allMatchers;
00081 };
00082
00083 class Where;
00084 class DiskLoc;
00085
00086 struct MatchDetails {
00087 MatchDetails() {
00088 reset();
00089 }
00090
00091 void reset() {
00092 loadedObject = false;
00093 elemMatchKey = 0;
00094 }
00095
00096 string toString() const {
00097 stringstream ss;
00098 ss << "loadedObject: " << loadedObject << " ";
00099 ss << "elemMatchKey: " << ( elemMatchKey ? elemMatchKey : "NULL" ) << " ";
00100 return ss.str();
00101 }
00102
00103 bool loadedObject;
00104 const char * elemMatchKey;
00105 };
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 class Matcher : boost::noncopyable {
00122 int matchesDotted(
00123 const char *fieldName,
00124 const BSONElement& toMatch, const BSONObj& obj,
00125 int compareOp, const ElementMatcher& bm, bool isArr , MatchDetails * details );
00126
00127 int matchesNe(
00128 const char *fieldName,
00129 const BSONElement &toMatch, const BSONObj &obj,
00130 const ElementMatcher&bm, MatchDetails * details );
00131
00132 public:
00133 static int opDirection(int op) {
00134 return op <= BSONObj::LTE ? -1 : 1;
00135 }
00136
00137 Matcher(const BSONObj &pattern, bool subMatcher = false);
00138
00139 ~Matcher();
00140
00141 bool matches(const BSONObj& j, MatchDetails * details = 0 );
00142
00143
00144
00145
00146 bool keyMatch() const { return !all && !haveSize && !hasArray && !haveNeg; }
00147
00148 bool atomic() const { return _atomic; }
00149
00150 bool hasType( BSONObj::MatchType type ) const;
00151
00152 string toString() const {
00153 return jsobj.toString();
00154 }
00155
00156 void addOrConstraint( const shared_ptr< FieldRangeVector > &frv ) {
00157 _orConstraints.push_back( frv );
00158 }
00159
00160 void popOrClause() {
00161 _orMatchers.pop_front();
00162 }
00163
00164 bool sameCriteriaCount( const Matcher &other ) const;
00165
00166 private:
00167
00168
00169 Matcher( const Matcher &other, const BSONObj &constrainIndexKey );
00170
00171 void addBasic(const BSONElement &e, int c, bool isNot) {
00172
00173 if ( e.type() == MinKey || e.type() == MaxKey )
00174 return;
00175 basics.push_back( ElementMatcher( e , c, isNot ) );
00176 }
00177
00178 void addRegex(const char *fieldName, const char *regex, const char *flags, bool isNot = false);
00179 bool addOp( const BSONElement &e, const BSONElement &fe, bool isNot, const char *& regex, const char *&flags );
00180
00181 int valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm);
00182
00183 bool parseOrNor( const BSONElement &e, bool subMatcher );
00184 void parseOr( const BSONElement &e, bool subMatcher, list< shared_ptr< Matcher > > &matchers );
00185
00186 Where *where;
00187 BSONObj jsobj;
00188 BSONObj constrainIndexKey_;
00189 vector<ElementMatcher> basics;
00190 bool haveSize;
00191 bool all;
00192 bool hasArray;
00193 bool haveNeg;
00194
00195
00196
00197
00198
00199
00200 bool _atomic;
00201
00202 RegexMatcher regexs[4];
00203 int nRegex;
00204
00205
00206 vector< shared_ptr< BSONObjBuilder > > _builders;
00207 list< shared_ptr< Matcher > > _orMatchers;
00208 list< shared_ptr< Matcher > > _norMatchers;
00209 vector< shared_ptr< FieldRangeVector > > _orConstraints;
00210
00211 friend class CoveredIndexMatcher;
00212 };
00213
00214
00215 class CoveredIndexMatcher : boost::noncopyable {
00216 public:
00217 CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKeyPattern , bool alwaysUseRecord=false );
00218 bool matches(const BSONObj &o) { return _docMatcher->matches( o ); }
00219 bool matches(const BSONObj &key, const DiskLoc &recLoc , MatchDetails * details = 0 , bool keyUsable = true );
00220 bool matchesCurrent( Cursor * cursor , MatchDetails * details = 0 );
00221 bool needRecord() { return _needRecord; }
00222
00223 Matcher& docMatcher() { return *_docMatcher; }
00224
00225
00226 void advanceOrClause( const shared_ptr< FieldRangeVector > &frv ) {
00227 _docMatcher->addOrConstraint( frv );
00228
00229
00230
00231 _docMatcher->popOrClause();
00232 }
00233
00234 CoveredIndexMatcher *nextClauseMatcher( const BSONObj &indexKeyPattern, bool alwaysUseRecord=false ) {
00235 return new CoveredIndexMatcher( _docMatcher, indexKeyPattern, alwaysUseRecord );
00236 }
00237 private:
00238 CoveredIndexMatcher(const shared_ptr< Matcher > &docMatcher, const BSONObj &indexKeyPattern , bool alwaysUseRecord=false );
00239 void init( bool alwaysUseRecord );
00240 shared_ptr< Matcher > _docMatcher;
00241 Matcher _keyMatcher;
00242
00243 bool _needRecord;
00244 bool _needRecordReject;
00245 bool _useRecordOnly;
00246 };
00247
00248 }