فهرست منبع

ref #3428: All parser tests pass! (For one brief shining moment).

Brennan Chesley 12 سال پیش
والد
کامیت
fc1560ca07

+ 1 - 3
lib/pipeline/matcher/ArrayFilterEntries.js

@@ -94,9 +94,7 @@ proto.contains = function contains( elem ) { //  const BSONElement& elem
 			if(Value.compare(elem, this._equalities[i]) === 0) {
 				return true;
 			}
-		} else {
-			return false;
-		}
+		} 
 	}
 	return false;
 };

+ 2 - 0
lib/pipeline/matcher/ExistsMatchExpression.js

@@ -59,6 +59,8 @@ proto.init = function init( path ) { //  const StringData& path
  */
 proto.matchesSingleElement = function matchesSingleElement( e ) { //  const BSONElement& e
 // File: expression_leaf.cpp lines: 282-283
+	if(typeof(e) == 'undefined')
+		return false;
 	return !(typeof(e) == 'object') || Object.keys(e).length > 0;
 };
 

+ 4 - 0
lib/pipeline/matcher/InMatchExpression.js

@@ -35,6 +35,10 @@ proto._matchesRealElement = function _matchesRealElement( e ) { //  const BSONEl
 	for (var i = 0; i < this._arrayEntries.numRegexes(); i++) {
 		if(e.match && e.match(this._arrayEntries.regex(i)._regex)) {
 			return true;
+		} else if (e instanceof RegExp) {
+			if(e.toString() == this._arrayEntries.regex(i)._regex.toString()) {
+				return true;
+			}
 		}
 	}
 	return false;

+ 1 - 1
lib/pipeline/matcher/LeafMatchExpression.js

@@ -50,7 +50,7 @@ proto.initPath = function initPath( path ) { //  const StringData& path
 proto.matches = function matches( doc, details ) { //  const MatchableDocument* doc, MatchDetails* details
 // File: expression_leaf.cpp lines: 37-48
 	var tDoc = ElementPath.objAtPath( doc, this._path );
-	if(typeof(tDoc) != 'object') {
+	if(tDoc instanceof RegExp || typeof(tDoc) != 'object') {
 		return this.matchesSingleElement(tDoc);
 	}
 	var docKeys = Object.keys(tDoc);

+ 4 - 4
lib/pipeline/matcher/MatchExpressionParser.js

@@ -429,10 +429,10 @@ proto._parseNot = function _parseNot(name, element){
 proto._parseRegexDocument = function _parseRegexDocument(name, doc){
 	// File: expression_parser.cpp lines: 402-442
 	var regex = '', regexOptions = '', e;
-	debugger;
+	
 	if(doc['$regex']) {
-		if(doc['$regex'] instanceof RegExp) {
-			e = doc['$regex'];
+		e = doc['$regex'];
+		if(e instanceof RegExp) {
 			var str = e.toString(),
 				flagIndex = 0;
 			for (var c = str.length; c > 0; c--){
@@ -443,7 +443,7 @@ proto._parseRegexDocument = function _parseRegexDocument(name, doc){
 			}
 			regex = (flagIndex? str : str.substr(1, flagIndex-1));
 			regexOptions = str.substr(flagIndex, str.length);
-		} else if (e instanceof String) {
+		} else if (typeof(e) == 'string' || e instanceof String) {
 			regex = e;
 		} else {
 			return {code:ErrorCodes.BAD_VALUE, description:"$regex has to be a string"};

+ 51 - 21
lib/pipeline/matcher/TypeMatchExpression.js

@@ -92,30 +92,60 @@ proto.init = function init( path,type ) { //  const StringData& path, int type
  * @param
  *
  */
-/*
+
 proto.matches = function matches( doc,details ) { //  const MatchableDocument* doc, MatchDetails* details
 // File: expression_leaf.cpp lines: 318-332
-//     bool TypeMatchExpression::matches( const MatchableDocument* doc, MatchDetails* details ) const {
-//         boost::scoped_ptr<ElementIterator> cursor( doc->getIterator( _elementPath ) );
-//         while ( cursor->more() ) {
-//             ElementIterator::Context e = cursor->next();
-//             if ( e.outerArray() )
-//                 continue;
-// 
-//             if ( !matchesSingleElement( e.element() ) )
-//                 continue;
-//             if ( details && details->needRecord() && !e.arrayOffset().eoo() ) {
-//                 details->setElemMatchKey( e.arrayOffset().fieldName() );
-//             }
-//             return true;
-//         }
-//         return false;
-//     }
-	var tDoc = ElementPath.objAtPath( doc, this._path );
+	return this._matches(doc,this._path,details);
+};
+
+proto._matches = function _matches(doc,path,details) {
+	var element, k, item,
+		curr = doc;
+	for (k = 0; k < path.length; k++) {
+		item = curr[path[k]];
+		if (item instanceof Object && item.constructor === Object) {
+			curr = item;
+			continue;
+		} else if (item instanceof Object && item.constructor === Array) {
+			if (k == path.length-1) {
+				curr = item;
+				break; // this is the end of the path, so check this array
+			} else if (!(isNaN(parseInt(path[k+1], 10)))) {
+				curr = item;
+				continue; // the *next* path section is an item in the array so we don't check this whole array
+			}
+			// otherwise, check each item in the array against the rest of the path
+			for(var ii = 0, il = item.length; ii < il; ii++){
+				var subitem = item[ii];
+				if (subitem.constructor !== Object) continue;	// can't look for a subfield in a non-object value.
+				if (this._matches(subitem, path.slice(k), null)) { // check the item against the rest of the path
+					if (details && details.needRecord())
+						details.setElemMatchKey(ii.toString());
+					return true;
+				}
+			}
+			return false; // checked all items in the array and found no matches
+		}
+	}
+
+	// we got the whole path, now check it
+	element = item;
+
+	//var amIRoot = (element.length === 0);
+
+	if (!this.matchesSingleElement(element, details))
+		return false;
+
+	/*
+	if (!amIRoot && details && details.needRecord() {
+		details.setElemMatchKey(element);
+	}
+	*/
+	return true;
+}
 
 
 
-};*/
 
 klass.typeNumber = function typeNumber( e ){
 	if(e === undefined)
@@ -131,13 +161,13 @@ klass.typeNumber = function typeNumber( e ){
 	if(typeof(e) == 'object') {
 		if(e instanceof Array)
 			return 4;
-		if(e instanceof Regexp)
+		if(e instanceof RegExp)
 			return 11;
 		if(e instanceof Date)
 			return 9;
 		if(e.constructor.name == 'MinKey')
 			return -1;
-		if(e.construcor.name == 'MAxKey')
+		if(e.constructor.name == 'MAxKey')
 			return 127;
 	}
 	return 42; // Can't tell

+ 4 - 4
test/lib/pipeline/matcher/MatchExpressionParser.js

@@ -327,7 +327,7 @@ module.exports = {
 			var a = /^a/;
 			var b = /B/i;
 			var q = {'a': {'$in': [a,b,"2",4]}};
-			debugger;
+
 			var res = parser.parse( q );
 			assert.strictEqual( res.code,'OK',res.description );
 			assert.ok( res.result.matches({'a':'ax'}) );
@@ -416,13 +416,13 @@ module.exports = {
 
 			var res = parser.parse( q );
 			assert.strictEqual( res.code,'OK',res.description );
-			assert.ok( res.result.matches({'x':'abc'}) );
-			assert.ok( ! res.result.matches({'y':'AC'}) );
+			assert.ok( ! res.result.matches({'x':'abc'}) );
+			assert.ok( res.result.matches({'y':'AC'}) );
 		},
 		"Should parse and match String $type": function() {
 			var parser = new MatchExpressionParser();
 			var q = {'x':{'$type': 2 }};
-
+			debugger;
 			var res = parser.parse( q );
 			assert.strictEqual( res.code,'OK',res.description );
 			assert.ok( res.result.matches({'x': 'abc'}) );