Explorar o código

EAGLESIX-2716: port should be complete -testcases

Jake Delaney %!s(int64=11) %!d(string=hai) anos
pai
achega
9c80898b67

+ 15 - 0
lib/pipeline/expressions/Helpers.js

@@ -0,0 +1,15 @@
+module.exports = {
+	//Returns an object containing unique values. All keys are the same as the corresponding value.
+	arrayToSet : function arrayToSet(array){
+
+		var set = {};
+
+		// This ensures no duplicates.
+		array.forEach(function (element) {
+			var elementString = JSON.stringify(element);
+			set[elementString] = element;
+		});
+
+		return set;
+	}
+}

+ 32 - 58
lib/pipeline/expressions/SetIsSubsetExpression.js

@@ -8,6 +8,7 @@
  * @module mungedb-aggregate
  * @constructor
  **/
+
 var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
 	this.nargs = 2;
 	if (arguments.length !== 2) throw new Error("two args expected");
@@ -21,8 +22,25 @@ var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
 	});
 
 
+// lhs should be array, rhs should be set (object). See arrayToSet implementation.
+var setIsSubsetHelper = function setIsSubsetHelper(lhs, rhs){
+
+	var lset = Helpers.arrayToSet(lhs);
+		rkeys = Object.keys(rhs);
+	// do not shortcircuit when lhs.size() > rhs.size()
+	// because lhs can have redundant entries
+	Object.keys(lset).forEach(function (lkey){
+		if (rkeys.indexOf(lkey) < 0){
+			return false;
+		}
+	});
+
+	return true;
+};
+
 var Optimized = function Optimized(cachedRhsSet, operands) {
 	this.operands = operands;
+	this._cachedRhsSet = cachedRhsSet;
 }
 
 Optimized.prototype = Object.create(SetIsSubsetExpression.prototype, {
@@ -31,56 +49,30 @@ Optimized.prototype = Object.create(SetIsSubsetExpression.prototype, {
 	}
 });
 
-Optimized.prototype.setIsSubsetHelper = function setIsSubsetHelper(vars){
-		// do not shortcircuit when lhs.size() > rhs.size()
-		// because lhs can have redundant entries
-		lhs.forEach(function (item){
-			if (! rhs.contains(item)){
-				return false
-			}
-		});
-
-		return true;
-};
-
 Optimized.prototype.evaluateInternal = function evaluateInternal(vars){
-	lhs = operands[0].evaluateInternal(vars);
-	rhs = operands[1].evaluateInternal(vars);
+	lhs = this.operands[0].evaluateInternal(vars);
 
 	if (!(lhs instanceof Array)) throw new Error("uassert 17046: both operands of " + this.getOpName() + "  must be arrays. Second argument is of type " + typeof lhs);
-	if (!(rhs instanceof Array)) throw new Error("uassert 17042: both operands of " + this.getOpName() + "  must be arrays. Second argument is of type " + typeof rhs);
-
-	return setIsSubsetHelper(lhs, arrayToSet(rhs));
+	
+	return setIsSubsetHelper(lhs, this._cachedRhsSet);
 };
 
 // DEPENDENCIES
 var Value = require("../Value"),
-	Expression = require("./Expression");
+	Expression = require("./Expression"),
+	Helpers = require("./Helpers.js");
 
 // PROTOTYPE MEMBERS
 proto.getOpName = function getOpName() {
 	return "$setissubset";
 };
 
-//Returns an object containing unique values. All keys are the same as the corresponding value.
-proto.arrayToSet = function arrayToSet(array){
-	var set = {};
-
-	// This ensures no duplicates.
-	array.forEach(function (element) {
-		var elementString = JSON.stringify(element);
-		set[elementString] = element;
-	});
-
-	return set;
-};
-
 proto.optimize = function optimize(cachedRhsSet, operands) {
 
 	// perform basic optimizations
-	var optimized = this.optimize();
+	var optimized = base.optimize.call(this);
 
-	// if NaryExoressuib.optimize() created a new value, return it directly
+	// if NaryExpression.optimize() created a new value, return it directly
 	if(optimized != this){
 		return optimized;
 	}
@@ -91,7 +83,7 @@ proto.optimize = function optimize(cachedRhsSet, operands) {
 
 		if (!(rhs instanceof Array)) throw new Error("uassert 17311: both operands of " + this.getOpName() + "  must be arrays. Second argument is of type " + typeof rhs);
 
-		return new Optimized(proto.arrayToSet(rhs), operands);
+		return new Optimized(Helpers.arrayToSet(rhs), this.operands);
 	}
 
 	return optimized;
@@ -99,34 +91,16 @@ proto.optimize = function optimize(cachedRhsSet, operands) {
 };
 
 /**
- * Takes 2 arrays. Returns true if the second is a subset of the first. Returns false otherwise.
+ * Takes 2 arrays. Returns true if the first is a subset of the second. Returns false otherwise.
  * @method evaluateInternal
  **/
 proto.evaluateInternal = function evaluateInternal(vars) {
-	var array1 = this.operands[0].evaluateInternal(vars),
-		array2 = this.operands[1].evaluateInternal(vars);
-	if (!(array1 instanceof Array)) throw new Error(this.getOpName() + ": object 1 must be an array. Got a(n) " + typeof array1);
-	if (!(array2 instanceof Array)) throw new Error(this.getOpName() + ": object 2 must be an array. Got a(n) " + typeof array1);
-
-	var sizeOfArray1 = array1.length;
-	var sizeOfArray2 = array2.length;
-	var outerLoop = 0;
-	var innerLoop = 0;
-	for (outerLoop = 0; outerLoop < sizeOfArray1; outerLoop++) {
-		for (innerLoop = 0; innerLoop < sizeOfArray2; innerLoop++) {
-			if (array2[outerLoop] == array1[innerLoop])
-				break;
-		}
+	var lhs = this.operands[0].evaluateInternal(vars),
+		rhs = this.operands[1].evaluateInternal(vars);
+	if (!(lhs instanceof Array)) throw new Error(this.getOpName() + ": object 1 must be an array. Got a(n) " + typeof lhs);
+	if (!(rhs instanceof Array)) throw new Error(this.getOpName() + ": object 2 must be an array. Got a(n) " + typeof rhs);
 
-		/* If the above inner loop was not broken at all then
-		 array2[i] is not present in array1[] */
-		if (innerLoop == sizeOfArray2)
-			return false;
-	}
-
-	/* If we reach here then all elements of array2[]
-	 are present in array1[] */
-	return true;
+	return setIsSubsetHelper(lhs, Helpers.arrayToSet(rhs));
 };
 
 /** Register Expression */