summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <mathias@10gen.com>2013-10-22 13:46:42 -0400
committerMathias Stearn <mathias@10gen.com>2013-11-13 19:44:41 -0500
commit1f9ac013237d1b6ba2fa17769d6dac59e515f373 (patch)
tree18873576515046d521e46b1f3014db85bbc8d43c
parent06cfa88df67067b7e8108b283a604f0e9169d0a3 (diff)
downloadmongo-1f9ac013237d1b6ba2fa17769d6dac59e515f373.tar.gz
SERVER-11692 step 3: Pass Variables as pointer rather than const ref.
This is just changing the function signatures and callers, not how Variables is used.
-rw-r--r--src/mongo/db/pipeline/document_source.h4
-rw-r--r--src/mongo/db/pipeline/document_source_group.cpp6
-rw-r--r--src/mongo/db/pipeline/document_source_project.cpp3
-rw-r--r--src/mongo/db/pipeline/document_source_redact.cpp14
-rw-r--r--src/mongo/db/pipeline/document_source_sort.cpp4
-rw-r--r--src/mongo/db/pipeline/expression.cpp112
-rw-r--r--src/mongo/db/pipeline/expression.h105
-rw-r--r--src/mongo/dbtests/expressiontests.cpp5
8 files changed, 132 insertions, 121 deletions
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h
index 75c377cef13..90b68241893 100644
--- a/src/mongo/db/pipeline/document_source.h
+++ b/src/mongo/db/pipeline/document_source.h
@@ -795,8 +795,8 @@ namespace mongo {
private:
DocumentSourceRedact(const intrusive_ptr<ExpressionContext>& expCtx,
const intrusive_ptr<Expression>& previsit);
- boost::optional<Document> redactObject(const Variables& in);
- Value redactValue(const Variables& vars, const Value& in);
+ boost::optional<Document> redactObject(Variables* in);
+ Value redactValue(Variables* vars, const Value& in);
intrusive_ptr<Expression> _expression;
};
diff --git a/src/mongo/db/pipeline/document_source_group.cpp b/src/mongo/db/pipeline/document_source_group.cpp
index 32b3c788c2e..58d51f62816 100644
--- a/src/mongo/db/pipeline/document_source_group.cpp
+++ b/src/mongo/db/pipeline/document_source_group.cpp
@@ -365,10 +365,10 @@ namespace mongo {
memoryUsageBytes = 0;
}
- const Variables vars(*input);
+ Variables vars(*input);
/* get the _id value */
- Value id = pIdExpression->evaluate(vars);
+ Value id = pIdExpression->evaluate(&vars);
/* treat missing values the same as NULL SERVER-4674 */
if (id.missing())
@@ -400,7 +400,7 @@ namespace mongo {
/* tickle all the accumulators for the group we found */
dassert(numAccumulators == group.size());
for (size_t i = 0; i < numAccumulators; i++) {
- group[i]->process(vpExpression[i]->evaluate(vars), _doingMerge);
+ group[i]->process(vpExpression[i]->evaluate(&vars), _doingMerge);
memoryUsageBytes += group[i]->memUsageForSorter();
}
diff --git a/src/mongo/db/pipeline/document_source_project.cpp b/src/mongo/db/pipeline/document_source_project.cpp
index bf92f0174d6..64f942e85e2 100644
--- a/src/mongo/db/pipeline/document_source_project.cpp
+++ b/src/mongo/db/pipeline/document_source_project.cpp
@@ -65,7 +65,8 @@ namespace mongo {
If we're excluding fields at the top level, leave out the _id if
it is found, because we took care of it above.
*/
- pEO->addToDocument(out, *input, Variables(*input));
+ Variables vars(*input);
+ pEO->addToDocument(out, *input, &vars);
#if defined(_DEBUG)
if (!_simpleProjection.getSpec().isEmpty()) {
diff --git a/src/mongo/db/pipeline/document_source_redact.cpp b/src/mongo/db/pipeline/document_source_redact.cpp
index 19bc8d3a61a..31877c4d27d 100644
--- a/src/mongo/db/pipeline/document_source_redact.cpp
+++ b/src/mongo/db/pipeline/document_source_redact.cpp
@@ -63,7 +63,7 @@ namespace mongo {
<< "PRUNE" << pruneVal
<< "KEEP" << keepVal));
- if (boost::optional<Document> result = redactObject(vars)) {
+ if (boost::optional<Document> result = redactObject(&vars)) {
return result;
}
}
@@ -71,12 +71,12 @@ namespace mongo {
return boost::none;
}
- Value DocumentSourceRedact::redactValue(const Variables& vars, const Value& in) {
+ Value DocumentSourceRedact::redactValue(Variables* vars, const Value& in) {
const BSONType valueType = in.getType();
if (valueType == Object) {
- Variables recurse = vars;
+ Variables recurse = *vars;
recurse.current = in;
- const boost::optional<Document> result = redactObject(recurse);
+ const boost::optional<Document> result = redactObject(&recurse);
if (result) {
return Value(*result);
}
@@ -106,18 +106,18 @@ namespace mongo {
}
}
- boost::optional<Document> DocumentSourceRedact::redactObject(const Variables& in) {
+ boost::optional<Document> DocumentSourceRedact::redactObject(Variables* in) {
const Value expressionResult = _expression->evaluate(in);
if (expressionResult == keepVal) {
- return in.current.getDocument();
+ return in->current.getDocument();
}
else if (expressionResult == pruneVal) {
return boost::optional<Document>();
}
else if (expressionResult == descendVal) {
MutableDocument out;
- FieldIterator fields(in.current.getDocument());
+ FieldIterator fields(in->current.getDocument());
while (fields.more()) {
const Document::FieldPair field(fields.next());
const Value val = redactValue(in, field.second);
diff --git a/src/mongo/db/pipeline/document_source_sort.cpp b/src/mongo/db/pipeline/document_source_sort.cpp
index 3f43b8ffd8b..f4e4e9db4f9 100644
--- a/src/mongo/db/pipeline/document_source_sort.cpp
+++ b/src/mongo/db/pipeline/document_source_sort.cpp
@@ -278,11 +278,11 @@ namespace mongo {
return vSortKey[0]->evaluate(d);
}
- const Variables vars(d);
+ Variables vars(d);
vector<Value> keys;
keys.reserve(vSortKey.size());
for (size_t i=0; i < vSortKey.size(); i++) {
- keys.push_back(vSortKey[i]->evaluate(vars));
+ keys.push_back(vSortKey[i]->evaluate(&vars));
}
return Value::consume(keys);
}
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index 3772e6dad9e..c32081050ec 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -345,7 +345,7 @@ namespace {
/* ------------------------- ExpressionAdd ----------------------------- */
- Value ExpressionAdd::evaluateInternal(const Variables& vars) const {
+ Value ExpressionAdd::evaluateInternal(Variables* vars) const {
/*
We'll try to return the narrowest possible result value. To do that
@@ -413,7 +413,7 @@ namespace {
/* ------------------------- ExpressionAllElementsTrue -------------------------- */
- Value ExpressionAllElementsTrue::evaluateInternal(const Variables& vars) const {
+ Value ExpressionAllElementsTrue::evaluateInternal(Variables* vars) const {
const Value arr = vpOperand[0]->evaluateInternal(vars);
uassert(17040, str::stream() << getOpName() << "'s argument must be an array, but is "
<< typeName(arr.getType()),
@@ -461,7 +461,7 @@ namespace {
Evaluate and coerce the last argument to a boolean. If it's false,
then we can replace this entire expression.
*/
- bool last = pLast->evaluateInternal(Variables()).coerceToBool();
+ bool last = pConst->getValue().coerceToBool();
if (!last) {
intrusive_ptr<ExpressionConstant> pFinal(
ExpressionConstant::create(Value(false)));
@@ -491,7 +491,7 @@ namespace {
return pE;
}
- Value ExpressionAnd::evaluateInternal(const Variables& vars) const {
+ Value ExpressionAnd::evaluateInternal(Variables* vars) const {
const size_t n = vpOperand.size();
for(size_t i = 0; i < n; ++i) {
Value pValue(vpOperand[i]->evaluateInternal(vars));
@@ -509,7 +509,7 @@ namespace {
/* ------------------------- ExpressionAnyElementTrue -------------------------- */
- Value ExpressionAnyElementTrue::evaluateInternal(const Variables& vars) const {
+ Value ExpressionAnyElementTrue::evaluateInternal(Variables* vars) const {
const Value arr = vpOperand[0]->evaluateInternal(vars);
uassert(17041, str::stream() << getOpName() << "'s argument must be an array, but is "
<< typeName(arr.getType()),
@@ -563,7 +563,7 @@ namespace {
pExpression->addDependencies(deps);
}
- Value ExpressionCoerceToBool::evaluateInternal(const Variables& vars) const {
+ Value ExpressionCoerceToBool::evaluateInternal(Variables* vars) const {
Value pResult(pExpression->evaluateInternal(vars));
bool b = pResult.coerceToBool();
if (b)
@@ -631,7 +631,7 @@ namespace {
};
}
- Value ExpressionCompare::evaluateInternal(const Variables& vars) const {
+ Value ExpressionCompare::evaluateInternal(Variables* vars) const {
Value pLeft(vpOperand[0]->evaluateInternal(vars));
Value pRight(vpOperand[1]->evaluateInternal(vars));
@@ -659,7 +659,7 @@ namespace {
/* ------------------------- ExpressionConcat ----------------------------- */
- Value ExpressionConcat::evaluateInternal(const Variables& vars) const {
+ Value ExpressionConcat::evaluateInternal(Variables* vars) const {
const size_t n = vpOperand.size();
StringBuilder result;
@@ -685,7 +685,7 @@ namespace {
/* ----------------------- ExpressionCond ------------------------------ */
- Value ExpressionCond::evaluateInternal(const Variables& vars) const {
+ Value ExpressionCond::evaluateInternal(Variables* vars) const {
Value pCond(vpOperand[0]->evaluateInternal(vars));
int idx = pCond.coerceToBool() ? 1 : 2;
return vpOperand[idx]->evaluateInternal(vars);
@@ -758,7 +758,7 @@ namespace {
/* nothing to do */
}
- Value ExpressionConstant::evaluateInternal(const Variables& vars) const {
+ Value ExpressionConstant::evaluateInternal(Variables* vars) const {
return pValue;
}
@@ -774,7 +774,7 @@ namespace {
/* ---------------------- ExpressionDayOfMonth ------------------------- */
- Value ExpressionDayOfMonth::evaluateInternal(const Variables& vars) const {
+ Value ExpressionDayOfMonth::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_mday);
@@ -787,7 +787,7 @@ namespace {
/* ------------------------- ExpressionDayOfWeek ----------------------------- */
- Value ExpressionDayOfWeek::evaluateInternal(const Variables& vars) const {
+ Value ExpressionDayOfWeek::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_wday+1); // MySQL uses 1-7 tm uses 0-6
@@ -800,7 +800,7 @@ namespace {
/* ------------------------- ExpressionDayOfYear ----------------------------- */
- Value ExpressionDayOfYear::evaluateInternal(const Variables& vars) const {
+ Value ExpressionDayOfYear::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_yday+1); // MySQL uses 1-366 tm uses 0-365
@@ -813,7 +813,7 @@ namespace {
/* ----------------------- ExpressionDivide ---------------------------- */
- Value ExpressionDivide::evaluateInternal(const Variables& vars) const {
+ Value ExpressionDivide::evaluateInternal(Variables* vars) const {
Value lhs = vpOperand[0]->evaluateInternal(vars);
Value rhs = vpOperand[1]->evaluateInternal(vars);
@@ -910,7 +910,7 @@ namespace {
void ExpressionObject::addToDocument(
MutableDocument& out,
const Document& currentDoc,
- const Variables& vars
+ Variables* vars
) const
{
FieldMap::const_iterator end = _expressions.end();
@@ -1045,7 +1045,7 @@ namespace {
return _expressions.size() + (_excludeId ? 0 : 1);
}
- Document ExpressionObject::evaluateDocument(const Variables& vars) const {
+ Document ExpressionObject::evaluateDocument(Variables* vars) const {
/* create and populate the result */
MutableDocument out (getSizeHint());
@@ -1055,7 +1055,7 @@ namespace {
return out.freeze();
}
- Value ExpressionObject::evaluateInternal(const Variables& vars) const {
+ Value ExpressionObject::evaluateInternal(Variables* vars) const {
return Value(evaluateDocument(vars));
}
@@ -1233,12 +1233,12 @@ namespace {
}
}
- Value ExpressionFieldPath::evaluateInternal(const Variables& vars) const {
+ Value ExpressionFieldPath::evaluateInternal(Variables* vars) const {
Value var;
switch (_baseVar) {
- case CURRENT: var = vars.current; break;
- case ROOT: var = vars.root; break;
- default: var = vars.rest[_fieldPath.getFieldName(0)]; break;
+ case CURRENT: var = vars->current; break;
+ case ROOT: var = vars->root; break;
+ default: var = vars->rest[_fieldPath.getFieldName(0)]; break;
}
if (_fieldPath.getPathLength() == 1)
@@ -1344,9 +1344,9 @@ namespace {
));
}
- Value ExpressionLet::evaluateInternal(const Variables& originalVars) const {
- Variables newVars = originalVars;
- MutableDocument newRest(originalVars.rest);
+ Value ExpressionLet::evaluateInternal(Variables* originalVars) const {
+ Variables newVars = *originalVars;
+ MutableDocument newRest(originalVars->rest);
for (VariableMap::const_iterator it=_variables.begin(), end=_variables.end();
it != end; ++it) {
@@ -1361,7 +1361,7 @@ namespace {
}
newVars.rest = newRest.freeze();
- return _subExpression->evaluateInternal(newVars);
+ return _subExpression->evaluateInternal(&newVars);
}
void ExpressionLet::addDependencies(set<string>& deps, vector<string>* path) const {
@@ -1451,7 +1451,7 @@ namespace {
)));
}
- Value ExpressionMap::evaluateInternal(const Variables& originalVars) const {
+ Value ExpressionMap::evaluateInternal(Variables* originalVars) const {
const Value inputVal = _input->evaluateInternal(originalVars);
if (inputVal.nullish())
return Value(BSONNULL);
@@ -1465,11 +1465,11 @@ namespace {
if (input.empty())
return inputVal;
- MutableDocument newRest(originalVars.rest);
+ MutableDocument newRest(originalVars->rest);
vector<Value> output;
output.reserve(input.size());
for (size_t i=0; i < input.size(); i++) {
- Variables newVars = originalVars;
+ Variables newVars = *originalVars;
if (_varName == "CURRENT") { // Can't set ROOT (checked in parse())
newVars.current = input[i];
} else {
@@ -1477,7 +1477,7 @@ namespace {
newVars.rest = newRest.peek();
}
- Value toInsert = _each->evaluateInternal(newVars);
+ Value toInsert = _each->evaluateInternal(&newVars);
if (toInsert.missing())
toInsert = Value(BSONNULL); // can't insert missing values into array
@@ -1494,7 +1494,7 @@ namespace {
/* ------------------------- ExpressionMillisecond ----------------------------- */
- Value ExpressionMillisecond::evaluateInternal(const Variables& vars) const {
+ Value ExpressionMillisecond::evaluateInternal(Variables* vars) const {
Value date(vpOperand[0]->evaluateInternal(vars));
const int ms = date.coerceToDate() % 1000LL;
// adding 1000 since dates before 1970 would have negative ms
@@ -1508,7 +1508,7 @@ namespace {
/* ------------------------- ExpressionMinute -------------------------- */
- Value ExpressionMinute::evaluateInternal(const Variables& vars) const {
+ Value ExpressionMinute::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_min);
@@ -1521,7 +1521,7 @@ namespace {
/* ----------------------- ExpressionMod ---------------------------- */
- Value ExpressionMod::evaluateInternal(const Variables& vars) const {
+ Value ExpressionMod::evaluateInternal(Variables* vars) const {
Value lhs = vpOperand[0]->evaluateInternal(vars);
Value rhs = vpOperand[1]->evaluateInternal(vars);
@@ -1574,7 +1574,7 @@ namespace {
/* ------------------------ ExpressionMonth ----------------------------- */
- Value ExpressionMonth::evaluateInternal(const Variables& vars) const {
+ Value ExpressionMonth::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_mon + 1); // MySQL uses 1-12 tm uses 0-11
@@ -1587,7 +1587,7 @@ namespace {
/* ------------------------- ExpressionMultiply ----------------------------- */
- Value ExpressionMultiply::evaluateInternal(const Variables& vars) const {
+ Value ExpressionMultiply::evaluateInternal(Variables* vars) const {
/*
We'll try to return the narrowest possible result value. To do that
without creating intermediate Values, do the arithmetic for double
@@ -1634,7 +1634,7 @@ namespace {
/* ------------------------- ExpressionHour ----------------------------- */
- Value ExpressionHour::evaluateInternal(const Variables& vars) const {
+ Value ExpressionHour::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_hour);
@@ -1647,7 +1647,7 @@ namespace {
/* ----------------------- ExpressionIfNull ---------------------------- */
- Value ExpressionIfNull::evaluateInternal(const Variables& vars) const {
+ Value ExpressionIfNull::evaluateInternal(Variables* vars) const {
Value pLeft(vpOperand[0]->evaluateInternal(vars));
if (!pLeft.nullish())
return pLeft;
@@ -1683,7 +1683,8 @@ namespace {
// If all the operands are constant, we can replace this expression with a constant. Using
// an empty Variables since it will never be accessed.
if (constCount == n) {
- Value pResult(evaluateInternal(Variables()));
+ Variables emptyVars;
+ Value pResult(evaluateInternal(&emptyVars));
intrusive_ptr<Expression> pReplacement(
ExpressionConstant::create(pResult));
return pReplacement;
@@ -1725,7 +1726,8 @@ namespace {
Value constValue;
if (!constExprs.empty()) {
vpOperand = constExprs;
- constValue = evaluateInternal(Variables());
+ Variables emptyVars;
+ constValue = evaluateInternal(&emptyVars);
}
// now set the final expression list with constant (if any) at the end
@@ -1760,7 +1762,7 @@ namespace {
/* ------------------------- ExpressionNot ----------------------------- */
- Value ExpressionNot::evaluateInternal(const Variables& vars) const {
+ Value ExpressionNot::evaluateInternal(Variables* vars) const {
Value pOp(vpOperand[0]->evaluateInternal(vars));
bool b = pOp.coerceToBool();
@@ -1774,7 +1776,7 @@ namespace {
/* -------------------------- ExpressionOr ----------------------------- */
- Value ExpressionOr::evaluateInternal(const Variables& vars) const {
+ Value ExpressionOr::evaluateInternal(Variables* vars) const {
const size_t n = vpOperand.size();
for(size_t i = 0; i < n; ++i) {
Value pValue(vpOperand[i]->evaluateInternal(vars));
@@ -1812,7 +1814,7 @@ namespace {
Evaluate and coerce the last argument to a boolean. If it's true,
then we can replace this entire expression.
*/
- bool last = pLast->evaluateInternal(Variables()).coerceToBool();
+ bool last = pConst->getValue().coerceToBool();
if (last) {
intrusive_ptr<ExpressionConstant> pFinal(
ExpressionConstant::create(Value(true)));
@@ -1845,7 +1847,7 @@ namespace {
/* ------------------------- ExpressionSecond ----------------------------- */
- Value ExpressionSecond::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSecond::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_sec);
@@ -1867,7 +1869,7 @@ namespace {
/* ----------------------- ExpressionSetDifference ---------------------------- */
- Value ExpressionSetDifference::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSetDifference::evaluateInternal(Variables* vars) const {
const Value lhs = vpOperand[0]->evaluateInternal(vars);
const Value rhs = vpOperand[1]->evaluateInternal(vars);
@@ -1909,7 +1911,7 @@ namespace {
args.size() >= 2);
}
- Value ExpressionSetEquals::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSetEquals::evaluateInternal(Variables* vars) const {
const size_t n = vpOperand.size();
std::set<Value> lhs;
@@ -1940,7 +1942,7 @@ namespace {
/* ----------------------- ExpressionSetIntersection ---------------------------- */
- Value ExpressionSetIntersection::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSetIntersection::evaluateInternal(Variables* vars) const {
const size_t n = vpOperand.size();
ValueSet currentIntersection;
for (size_t i = 0; i < n; i++) {
@@ -1991,7 +1993,7 @@ namespace {
/* ----------------------- ExpressionSetIsSubset ---------------------------- */
- Value ExpressionSetIsSubset::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSetIsSubset::evaluateInternal(Variables* vars) const {
const Value lhs = vpOperand[0]->evaluateInternal(vars);
const Value rhs = vpOperand[1]->evaluateInternal(vars);
@@ -2023,7 +2025,7 @@ namespace {
/* ----------------------- ExpressionSetUnion ---------------------------- */
- Value ExpressionSetUnion::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSetUnion::evaluateInternal(Variables* vars) const {
ValueSet unionedSet;
const size_t n = vpOperand.size();
for (size_t i = 0; i < n; i++) {
@@ -2048,7 +2050,7 @@ namespace {
/* ----------------------- ExpressionSize ---------------------------- */
- Value ExpressionSize::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSize::evaluateInternal(Variables* vars) const {
Value array = vpOperand[0]->evaluateInternal(vars);
uassert(17124, str::stream() << "The argument to $size must be an Array, but was of type: "
@@ -2064,7 +2066,7 @@ namespace {
/* ----------------------- ExpressionStrcasecmp ---------------------------- */
- Value ExpressionStrcasecmp::evaluateInternal(const Variables& vars) const {
+ Value ExpressionStrcasecmp::evaluateInternal(Variables* vars) const {
Value pString1(vpOperand[0]->evaluateInternal(vars));
Value pString2(vpOperand[1]->evaluateInternal(vars));
@@ -2088,7 +2090,7 @@ namespace {
/* ----------------------- ExpressionSubstr ---------------------------- */
- Value ExpressionSubstr::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSubstr::evaluateInternal(Variables* vars) const {
Value pString(vpOperand[0]->evaluateInternal(vars));
Value pLower(vpOperand[1]->evaluateInternal(vars));
Value pLength(vpOperand[2]->evaluateInternal(vars));
@@ -2123,7 +2125,7 @@ namespace {
/* ----------------------- ExpressionSubtract ---------------------------- */
- Value ExpressionSubtract::evaluateInternal(const Variables& vars) const {
+ Value ExpressionSubtract::evaluateInternal(Variables* vars) const {
Value lhs = vpOperand[0]->evaluateInternal(vars);
Value rhs = vpOperand[1]->evaluateInternal(vars);
@@ -2177,7 +2179,7 @@ namespace {
/* ------------------------- ExpressionToLower ----------------------------- */
- Value ExpressionToLower::evaluateInternal(const Variables& vars) const {
+ Value ExpressionToLower::evaluateInternal(Variables* vars) const {
Value pString(vpOperand[0]->evaluateInternal(vars));
string str = pString.coerceToString();
boost::to_lower(str);
@@ -2191,7 +2193,7 @@ namespace {
/* ------------------------- ExpressionToUpper -------------------------- */
- Value ExpressionToUpper::evaluateInternal(const Variables& vars) const {
+ Value ExpressionToUpper::evaluateInternal(Variables* vars) const {
Value pString(vpOperand[0]->evaluateInternal(vars));
string str(pString.coerceToString());
boost::to_upper(str);
@@ -2205,7 +2207,7 @@ namespace {
/* ------------------------- ExpressionWeek ----------------------------- */
- Value ExpressionWeek::evaluateInternal(const Variables& vars) const {
+ Value ExpressionWeek::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
int dayOfWeek = date.tm_wday;
@@ -2234,7 +2236,7 @@ namespace {
/* ------------------------- ExpressionYear ----------------------------- */
- Value ExpressionYear::evaluateInternal(const Variables& vars) const {
+ Value ExpressionYear::evaluateInternal(Variables* vars) const {
Value pDate(vpOperand[0]->evaluateInternal(vars));
tm date = pDate.coerceToTm();
return Value(date.tm_year + 1900); // tm_year is years since 1900
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h
index ee02c7a945d..675aae9c694 100644
--- a/src/mongo/db/pipeline/expression.h
+++ b/src/mongo/db/pipeline/expression.h
@@ -45,7 +45,7 @@ namespace mongo {
class DocumentSource;
// TODO: Look into merging with ExpressionContext and possibly ObjectCtx.
- /// The state used as input to Expressions
+ /// The state used as input and working space for Expressions.
class Variables {
public:
/**
@@ -154,12 +154,19 @@ namespace mongo {
*/
virtual Value serialize(bool explain) const = 0;
- /// Evaluate expression with specified inputs and return result.
- Value evaluate(const Document& root) const { return evaluate(Variables(root)); }
- Value evaluate(const Document& root, const Value& current) const {
- return evaluate(Variables(root, current));
+ /// Evaluate expression with specified inputs and return result. (only used by tests)
+ Value evaluate(const Document& root) const {
+ Variables vars(root);
+ return evaluate(&vars);
}
- Value evaluate(const Variables& vars) const { return evaluateInternal(vars); }
+
+ /**
+ * Evaluate expression with specified inputs and return result.
+ *
+ * While vars is non-const, if properly constructed, subexpressions modifications to it
+ * should not effect outer expressions due to unique variable Ids.
+ */
+ Value evaluate(Variables* vars) const { return evaluateInternal(vars); }
/*
Utility class for parseObject() below.
@@ -237,7 +244,7 @@ namespace mongo {
* Should only be called by subclasses, but can't be protected because they need to call
* this function on each other.
*/
- virtual Value evaluateInternal(const Variables& vars) const = 0;
+ virtual Value evaluateInternal(Variables* vars) const = 0;
protected:
typedef vector<intrusive_ptr<Expression> > ExpressionVector;
@@ -321,7 +328,7 @@ namespace mongo {
class ExpressionAdd : public ExpressionVariadic<ExpressionAdd> {
public:
// virtuals from Expression
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -330,7 +337,7 @@ namespace mongo {
class ExpressionAllElementsTrue : public ExpressionFixedArity<ExpressionAllElementsTrue, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -339,7 +346,7 @@ namespace mongo {
public:
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -348,7 +355,7 @@ namespace mongo {
class ExpressionAnyElementTrue : public ExpressionFixedArity<ExpressionAnyElementTrue, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -358,7 +365,7 @@ namespace mongo {
// virtuals from ExpressionNary
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual Value serialize(bool explain) const;
static intrusive_ptr<ExpressionCoerceToBool> create(
@@ -389,7 +396,7 @@ namespace mongo {
};
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
static intrusive_ptr<Expression> parse(
@@ -407,7 +414,7 @@ namespace mongo {
class ExpressionConcat : public ExpressionVariadic<ExpressionConcat> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -416,7 +423,7 @@ namespace mongo {
typedef ExpressionFixedArity<ExpressionCond, 3> Base;
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
static intrusive_ptr<Expression> parse(
@@ -430,7 +437,7 @@ namespace mongo {
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual Value serialize(bool explain) const;
@@ -456,7 +463,7 @@ namespace mongo {
class ExpressionDayOfMonth : public ExpressionFixedArity<ExpressionDayOfMonth, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -464,7 +471,7 @@ namespace mongo {
class ExpressionDayOfWeek : public ExpressionFixedArity<ExpressionDayOfWeek, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -472,7 +479,7 @@ namespace mongo {
class ExpressionDayOfYear : public ExpressionFixedArity<ExpressionDayOfYear, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -480,7 +487,7 @@ namespace mongo {
class ExpressionDivide : public ExpressionFixedArity<ExpressionDivide, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -490,7 +497,7 @@ namespace mongo {
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual Value serialize(bool explain) const;
/*
@@ -552,7 +559,7 @@ namespace mongo {
class ExpressionHour : public ExpressionFixedArity<ExpressionHour, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -560,7 +567,7 @@ namespace mongo {
class ExpressionIfNull : public ExpressionFixedArity<ExpressionIfNull, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -570,7 +577,7 @@ namespace mongo {
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
static intrusive_ptr<Expression> parse(
@@ -603,7 +610,7 @@ namespace mongo {
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
static intrusive_ptr<Expression> parse(
@@ -625,7 +632,7 @@ namespace mongo {
class ExpressionMillisecond : public ExpressionFixedArity<ExpressionMillisecond, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char* getOpName() const;
};
@@ -633,7 +640,7 @@ namespace mongo {
class ExpressionMinute : public ExpressionFixedArity<ExpressionMinute, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -641,7 +648,7 @@ namespace mongo {
class ExpressionMod : public ExpressionFixedArity<ExpressionMod, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -649,7 +656,7 @@ namespace mongo {
class ExpressionMultiply : public ExpressionVariadic<ExpressionMultiply> {
public:
// virtuals from Expression
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -658,7 +665,7 @@ namespace mongo {
class ExpressionMonth : public ExpressionFixedArity<ExpressionMonth, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -666,7 +673,7 @@ namespace mongo {
class ExpressionNot : public ExpressionFixedArity<ExpressionNot, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -678,11 +685,11 @@ namespace mongo {
virtual bool isSimple();
virtual void addDependencies(set<string>& deps, vector<string>* path=NULL) const;
/** Only evaluates non inclusion expressions. For inclusions, use addToDocument(). */
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual Value serialize(bool explain) const;
/// like evaluate(), but return a Document instead of a Value-wrapped Document.
- Document evaluateDocument(const Variables& vars) const;
+ Document evaluateDocument(Variables* vars) const;
/** Evaluates with inclusions and adds results to passed in Mutable document
*
@@ -692,7 +699,7 @@ namespace mongo {
*/
void addToDocument(MutableDocument& ouput,
const Document& currentDoc,
- const Variables& vars
+ Variables* vars
) const;
// estimated number of fields that will be output
@@ -785,7 +792,7 @@ namespace mongo {
public:
// virtuals from Expression
virtual intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -794,7 +801,7 @@ namespace mongo {
class ExpressionSecond : public ExpressionFixedArity<ExpressionSecond, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -802,7 +809,7 @@ namespace mongo {
class ExpressionSetDifference : public ExpressionFixedArity<ExpressionSetDifference, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -810,7 +817,7 @@ namespace mongo {
class ExpressionSetEquals : public ExpressionVariadic<ExpressionSetEquals> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual void validateArguments(const ExpressionVector& args) const;
};
@@ -819,7 +826,7 @@ namespace mongo {
class ExpressionSetIntersection : public ExpressionVariadic<ExpressionSetIntersection> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -828,7 +835,7 @@ namespace mongo {
class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -837,7 +844,7 @@ namespace mongo {
public:
// virtuals from ExpressionNary
// virtual intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
virtual bool isAssociativeAndCommutative() const { return true; }
};
@@ -846,7 +853,7 @@ namespace mongo {
class ExpressionSize : public ExpressionFixedArity<ExpressionSize, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -854,7 +861,7 @@ namespace mongo {
class ExpressionStrcasecmp : public ExpressionFixedArity<ExpressionStrcasecmp, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -862,7 +869,7 @@ namespace mongo {
class ExpressionSubstr : public ExpressionFixedArity<ExpressionSubstr, 3> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -870,7 +877,7 @@ namespace mongo {
class ExpressionSubtract : public ExpressionFixedArity<ExpressionSubtract, 2> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -878,7 +885,7 @@ namespace mongo {
class ExpressionToLower : public ExpressionFixedArity<ExpressionToLower, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -886,7 +893,7 @@ namespace mongo {
class ExpressionToUpper : public ExpressionFixedArity<ExpressionToUpper, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -894,7 +901,7 @@ namespace mongo {
class ExpressionWeek : public ExpressionFixedArity<ExpressionWeek, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
@@ -902,7 +909,7 @@ namespace mongo {
class ExpressionYear : public ExpressionFixedArity<ExpressionYear, 1> {
public:
// virtuals from ExpressionNary
- virtual Value evaluateInternal(const Variables& vars) const;
+ virtual Value evaluateInternal(Variables* vars) const;
virtual const char *getOpName() const;
};
}
diff --git a/src/mongo/dbtests/expressiontests.cpp b/src/mongo/dbtests/expressiontests.cpp
index 1ab4d2a0483..ef6266abc48 100644
--- a/src/mongo/dbtests/expressiontests.cpp
+++ b/src/mongo/dbtests/expressiontests.cpp
@@ -1178,7 +1178,7 @@ namespace ExpressionTests {
/** A dummy child of ExpressionNary used for testing. */
class Testable : public ExpressionNary {
public:
- virtual Value evaluateInternal(const Variables& vars) const {
+ virtual Value evaluateInternal(Variables* vars) const {
// Just put all the values in a list. This is not associative/commutative so
// the results will change if a factory is provided and operations are reordered.
vector<Value> values;
@@ -1449,7 +1449,8 @@ namespace ExpressionTests {
prepareExpression();
Document document = fromBson( source() );
MutableDocument result;
- expression()->addToDocument( result, document, Variables(document) );
+ Variables vars(document);
+ expression()->addToDocument( result, document, &vars );
assertBinaryEqual( expected(), toBson( result.freeze() ) );
assertDependencies( expectedDependencies(), _expression );
ASSERT_EQUALS( expectedBsonRepresentation(), expressionToBson( _expression ) );