Browse Source

EAGLESIX-2708 expression Subtract ported to mongo 2.6.5

Jared Hall 11 years ago
parent
commit
6acb2bf656

+ 28 - 0
lib/pipeline/expressions/SubtractExpression.js

@@ -34,6 +34,34 @@ proto.getOpName = function getOpName(){
 proto.evaluateInternal = function evaluateInternal(vars) {
 	var left = this.operands[0].evaluateInternal(vars),
 		right = this.operands[1].evaluateInternal(vars);
+	if (typeof left === 'number' && typeof right === 'number') {
+		return left - right;
+	}
+	//NOTE: DEVIATION FROM MONGO: inlined left.nullish() || right.nullish()
+	else if (left === null || left === undefined || right === null || right === undefined) {
+		return null;
+	}
+	else if (left instanceof Date) {
+		if (right instanceof Date) {
+			return left - right;
+		}
+		else if (typeof right === 'number') {
+			var millisSinceEpoch = left - right;
+			return new Date(millisSinceEpoch);
+		} else {
+			throw new Error("uassert 16613: " +
+				"can't $subtract a " +
+				typeof right +
+				" from a Date");
+		}
+	}
+	else {
+		throw new Error("uassert 16556: " +
+			"can't $subtract a " +
+			typeof right +
+			" from a " +
+			typeof left);
+	}
 	if (left instanceof Date || right instanceof Date) throw new Error("$subtract does not support dates; code 16376");
 	return left - right;
 };

+ 89 - 7
test/lib/pipeline/expressions/SubtractExpression.js

@@ -1,7 +1,9 @@
 "use strict";
 var assert = require("assert"),
 		SubtractExpression = require("../../../../lib/pipeline/expressions/SubtractExpression"),
-		Expression = require("../../../../lib/pipeline/expressions/Expression");
+		Expression = require("../../../../lib/pipeline/expressions/Expression"),
+		VariablesIdGenerator = require("../../../../lib/pipeline/expressions/VariablesIdGenerator"),
+		VariablesParseState = require("../../../../lib/pipeline/expressions/VariablesParseState");
 
 
 module.exports = {
@@ -29,12 +31,92 @@ module.exports = {
 				"#evaluateInternal()": {
 
 						"should return the result of subtraction between two numbers": function testStuff() {
-								assert.strictEqual(Expression.parseOperand({
-										$subtract: ["$a", "$b"]
-								}).evaluateInternal({
-										a: 35636364,
-										b: -0.5656
-								}), 35636364 - (-0.5656));
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								result = expr.evaluate({a:2, b:1}),
+								expected = 1;
+							assert.equal(result, expected);
+						},
+
+						"should return null if left is null": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								result = expr.evaluate({a:null, b:1}),
+								expected = null;
+							assert.equal(result, expected);
+						},
+
+						"should return null if left is undefined": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								result = expr.evaluate({a:undefined, b:1}),
+								expected = null;
+							assert.equal(result, expected);
+						},
+
+						"should return null if right is null": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								result = expr.evaluate({a:2, b:null}),
+								expected = null;
+							assert.equal(result, expected);
+						},
+
+						"should return null if right is undefined": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								result = expr.evaluate({a:2, b:undefined}),
+								expected = null;
+							assert.equal(result, expected);
+						},
+
+						"should subtract 2 dates": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								date2 = new Date('Jan 3 1990'),
+								date1 = new Date('Jan 1 1990'),
+								result = expr.evaluate({a:date2, b:date1}),
+								expected = date2 - date1;
+							assert.equal(result, expected);
+						},
+
+						"should subtract a number of millis from a date": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								date2 = new Date('Jan 3 1990'),
+								millis = 24 * 60 * 60 * 1000,
+								result = expr.evaluate({a:date2, b:millis}),
+								expected = new Date(date2 - millis);
+							assert.equal(result, expected);
+						},
+
+						"should throw if left is not a date or number": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								date2 = {},
+								date1 = new Date();
+							assert.throws(function() {
+								expr.evaluate({a:date2, b:date1});
+							});
+						},
+
+						"should throw if right is not a date or number": function testStuff() {
+							var idGenerator = new VariablesIdGenerator(),
+								vps = new VariablesParseState(idGenerator),
+								expr = Expression.parseOperand({$subtract:["$a", "$b"]}, vps),
+								date2 = new Date(),
+								date1 = {};
+							assert.throws(function() {
+								expr.evaluate({a:date2, b:date1});
+							});
 						}
 				}