0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 17:10:48 +01:00

SERVER-8568 Add $sqrt aggregation expression

This commit is contained in:
James Cohan 2015-07-01 10:17:35 -04:00
parent 9a743c6fb3
commit 4f4e36b69b
3 changed files with 71 additions and 2 deletions

View File

@ -0,0 +1,43 @@
// SERVER-8568: Adding $sqrt expression
// For assertErrorCode.
load('jstests/aggregation/extras/utils.js');
(function() {
'use strict';
var coll = db.sqrt;
coll.drop();
assert.writeOK(coll.insert({_id: 0}));
// Helper for testing that op returns expResult.
function testOp(op, expResult) {
var pipeline = [{$project: {_id: 0, result: op}}];
assert.eq(coll.aggregate(pipeline).toArray(), [{result: expResult}]);
}
// Helper for testing that op results in error with code errorCode.
function testError(op, errorCode) {
var pipeline = [{$project: {_id: 0, result: op}}];
assertErrorCode(coll, pipeline, errorCode);
}
// Valid input: Numeric arg >= 0, null, or NaN.
testOp({$sqrt: [100]}, 10);
testOp({$sqrt: [0]}, 0);
// All types converted to doubles.
testOp({$sqrt: [NumberLong("100")]}, 10);
// LLONG_MAX is converted to a double.
testOp({$sqrt: [NumberLong("9223372036854775807")]}, 3037000499.97605);
// Null inputs result in null.
testOp({$sqrt: [null]}, null);
// NaN inputs result in NaN.
testOp({$sqrt: [NaN]}, NaN);
// Invalid input: non-numeric/non-null, arg is negative.
// Arg must be numeric or null.
testError({$sqrt: ["string"]}, 28715);
// Args cannot be negative.
testError({$sqrt: [-1]}, 28714);
}());

View File

@ -1321,7 +1321,6 @@ void ExpressionObject::addToDocument(MutableDocument& out,
if (dynamic_cast<ExpressionObject*>(it->second.get()) && pValue.getDocument().empty())
continue;
out.addField(fieldName, pValue);
}
}
@ -2407,7 +2406,6 @@ intrusive_ptr<Expression> ExpressionSetIsSubset::optimize() {
return new Optimized(arrayToSet(rhs), vpOperand);
}
return optimized;
}
@ -2470,6 +2468,30 @@ const char* ExpressionSize::getOpName() const {
return "$size";
}
/* ----------------------- ExpressionSqrt ---------------------------- */
Value ExpressionSqrt::evaluateInternal(Variables* vars) const {
Value argVal = vpOperand[0]->evaluateInternal(vars);
if (argVal.nullish())
return Value(BSONNULL);
uassert(28715,
str::stream() << "$sqrt only supports numeric types, not "
<< typeName(argVal.getType()),
argVal.numeric());
double argDouble = argVal.coerceToDouble();
uassert(28714,
"$sqrt's argument must be greater than or equal to 0",
argDouble >= 0 || std::isnan(argDouble));
return Value(sqrt(argDouble));
}
REGISTER_EXPRESSION("$sqrt", ExpressionSqrt::parse);
const char* ExpressionSqrt::getOpName() const {
return "$sqrt";
}
/* ----------------------- ExpressionStrcasecmp ---------------------------- */
Value ExpressionStrcasecmp::evaluateInternal(Variables* vars) const {

View File

@ -989,6 +989,10 @@ public:
const char* getOpName() const final;
};
class ExpressionSqrt final : public ExpressionFixedArity<ExpressionSqrt, 1> {
Value evaluateInternal(Variables* vars) const final;
const char* getOpName() const final;
};
class ExpressionStrcasecmp final : public ExpressionFixedArity<ExpressionStrcasecmp, 2> {
public: