Browse Source

EAGLESIX-2716: still some things to iron out

Jake Delaney 11 years ago
parent
commit
c5aebdfebc
1 changed files with 62 additions and 17 deletions
  1. 62 17
      lib/pipeline/expressions/SetIsSubsetExpression.js

+ 62 - 17
lib/pipeline/expressions/SetIsSubsetExpression.js

@@ -20,6 +20,39 @@ var SetIsSubsetExpression = module.exports = function SetIsSubsetExpression() {
 		}
 	});
 
+
+var Optimized = function Optimized(cachedRhsSet, operands) {
+	this.operands = operands;
+}
+
+Optimized.prototype = Object.create(SetIsSubsetExpression.prototype, {
+	constructor: {
+		value: Optimized
+	}
+});
+
+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);
+
+	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));
+};
+
 // DEPENDENCIES
 var Value = require("../Value"),
 	Expression = require("./Expression");
@@ -29,39 +62,51 @@ 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) {
 
-// This optimize needs to be done, eventually
+	// perform basic optimizations
+	var optimized = this.optimize();
 
-// // perfore basic optimizations
-//     intrusive_ptr<Expression> optimized = ExpressionNary::optimize();
+	// if NaryExoressuib.optimize() created a new value, return it directly
+	if(optimized != this){
+		return optimized;
+	}
 
-//     // if ExpressionNary::optimize() created a new value, return it directly
-//     if (optimized.get() != this)
-//         return optimized;
+	if (operands[1] instanceof ConstantExpression){
+		var ce = operands[1],
+			rhs = ce.getValue();
 
-//     if (ExpressionConstant* ec = dynamic_cast<ExpressionConstant*>(vpOperand[1].get())) {
-//         const Value rhs = ec->getValue();
-//         uassert(17311, str::stream() << "both operands of $setIsSubset must be arrays. Second "
-//                                      << "argument is of type: " << typeName(rhs.getType()),
-//                 rhs.getType() == Array);
+		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(arrayToSet(rhs), vpOperand);
-//     }
+		return new Optimized(proto.arrayToSet(rhs), operands);
+	}
 
-//     return optimized;
+	return optimized;
 
 };
 
 /**
- * Takes 2 arrays. Assigns the second array to the first array.
+ * Takes 2 arrays. Returns true if the second is a subset of the first. 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");
-	if (array2 instanceof Array) throw new Error(this.getOpName() + ": object 2 must be an array");
+	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;