From 1f9ac013237d1b6ba2fa17769d6dac59e515f373 Mon Sep 17 00:00:00 2001 From: Mathias Stearn Date: Tue, 22 Oct 2013 13:46:42 -0400 Subject: 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. --- src/mongo/db/pipeline/document_source.h | 4 +- src/mongo/db/pipeline/document_source_group.cpp | 6 +- src/mongo/db/pipeline/document_source_project.cpp | 3 +- src/mongo/db/pipeline/document_source_redact.cpp | 14 +-- src/mongo/db/pipeline/document_source_sort.cpp | 4 +- src/mongo/db/pipeline/expression.cpp | 112 +++++++++++----------- src/mongo/db/pipeline/expression.h | 105 ++++++++++---------- src/mongo/dbtests/expressiontests.cpp | 5 +- 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& expCtx, const intrusive_ptr& previsit); - boost::optional redactObject(const Variables& in); - Value redactValue(const Variables& vars, const Value& in); + boost::optional redactObject(Variables* in); + Value redactValue(Variables* vars, const Value& in); intrusive_ptr _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 result = redactObject(vars)) { + if (boost::optional 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 result = redactObject(recurse); + const boost::optional result = redactObject(&recurse); if (result) { return Value(*result); } @@ -106,18 +106,18 @@ namespace mongo { } } - boost::optional DocumentSourceRedact::redactObject(const Variables& in) { + boost::optional 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(); } 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 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 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& deps, vector* 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 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 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 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 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 > ExpressionVector; @@ -321,7 +328,7 @@ namespace mongo { class ExpressionAdd : public ExpressionVariadic { 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 { 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 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 { 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 optimize(); virtual void addDependencies(set& deps, vector* 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 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 parse( @@ -407,7 +414,7 @@ namespace mongo { class ExpressionConcat : public ExpressionVariadic { 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 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 parse( @@ -430,7 +437,7 @@ namespace mongo { // virtuals from Expression virtual intrusive_ptr optimize(); virtual void addDependencies(set& deps, vector* 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 { 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 { 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 { 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 { 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 optimize(); virtual void addDependencies(set& deps, vector* 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 { 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 { 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 optimize(); virtual Value serialize(bool explain) const; - virtual Value evaluateInternal(const Variables& vars) const; + virtual Value evaluateInternal(Variables* vars) const; virtual void addDependencies(set& deps, vector* path=NULL) const; static intrusive_ptr parse( @@ -603,7 +610,7 @@ namespace mongo { // virtuals from Expression virtual intrusive_ptr optimize(); virtual Value serialize(bool explain) const; - virtual Value evaluateInternal(const Variables& vars) const; + virtual Value evaluateInternal(Variables* vars) const; virtual void addDependencies(set& deps, vector* path=NULL) const; static intrusive_ptr parse( @@ -625,7 +632,7 @@ namespace mongo { class ExpressionMillisecond : public ExpressionFixedArity { 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 { 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 { 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 { 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 { 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 { 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& deps, vector* 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 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 { 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 { 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 { 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 { 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 { 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 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 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 ) ); -- cgit v1.2.1