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:
parent
9a743c6fb3
commit
4f4e36b69b
43
jstests/aggregation/bugs/server8568.js
Normal file
43
jstests/aggregation/bugs/server8568.js
Normal 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);
|
||||
}());
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user