diff options
Diffstat (limited to 'src/mongo/db/pipeline/expression.h')
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 428 |
1 files changed, 336 insertions, 92 deletions
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index 00e771784c2..ef9a3ae3f19 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -172,8 +172,8 @@ private: class Expression : public IntrusiveCounterUnsigned { public: - using Parser = - stdx::function<boost::intrusive_ptr<Expression>(BSONElement, const VariablesParseState&)>; + using Parser = stdx::function<boost::intrusive_ptr<Expression>( + const boost::intrusive_ptr<ExpressionContext>&, BSONElement, const VariablesParseState&)>; virtual ~Expression(){}; @@ -235,8 +235,10 @@ public: * Calls parseExpression() on any sub-document (including possibly the entire document) which * consists of a single field name starting with a '$'. */ - static boost::intrusive_ptr<Expression> parseObject(BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseObject( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * Parses a BSONObj which has already been determined to be a functional expression. @@ -244,8 +246,10 @@ public: * Throws an error if 'obj' does not contain exactly one field, or if that field's name does not * match a registered expression name. */ - static boost::intrusive_ptr<Expression> parseExpression(BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseExpression( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * Parses a BSONElement which is an argument to an Expression. @@ -254,8 +258,10 @@ public: * parseObject(), ExpressionFieldPath::parse(), ExpressionArray::parse(), or * ExpressionConstant::parse() as necessary. */ - static boost::intrusive_ptr<Expression> parseOperand(BSONElement exprElement, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseOperand( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement exprElement, + const VariablesParseState& vps); /* Produce a field path std::string with the field prefix removed. @@ -282,24 +288,10 @@ public: */ static void registerExpression(std::string key, Parser parser); - /** - * Injects the ExpressionContext so that it may be used during evaluation of the Expression. - * Construction of expressions is done at parse time, but the ExpressionContext isn't finalized - * until later, at which point it is injected using this method. - */ - void injectExpressionContext(const boost::intrusive_ptr<ExpressionContext>& expCtx) { - _expCtx = expCtx; - doInjectExpressionContext(); - } - protected: - typedef std::vector<boost::intrusive_ptr<Expression>> ExpressionVector; + Expression(const boost::intrusive_ptr<ExpressionContext>& expCtx) : _expCtx(expCtx) {} - /** - * Expressions which need to update their internal state when attaching to a new - * ExpressionContext should override this method. - */ - virtual void doInjectExpressionContext() {} + typedef std::vector<boost::intrusive_ptr<Expression>> ExpressionVector; const boost::intrusive_ptr<ExpressionContext>& getExpressionContext() const { return _expCtx; @@ -344,12 +336,13 @@ public: /// Allow subclasses the opportunity to validate arguments at parse time. virtual void validateArguments(const ExpressionVector& args) const {} - static ExpressionVector parseArguments(BSONElement bsonExpr, const VariablesParseState& vps); - - void doInjectExpressionContext() final; + static ExpressionVector parseArguments(const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps); protected: - ExpressionNary() {} + explicit ExpressionNary(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : Expression(expCtx) {} ExpressionVector vpOperand; }; @@ -358,19 +351,29 @@ protected: template <typename SubClass> class ExpressionNaryBase : public ExpressionNary { public: - static boost::intrusive_ptr<Expression> parse(BSONElement bsonExpr, - const VariablesParseState& vps) { - boost::intrusive_ptr<ExpressionNaryBase> expr = new SubClass(); - ExpressionVector args = parseArguments(bsonExpr, vps); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps) { + boost::intrusive_ptr<ExpressionNaryBase> expr = new SubClass(expCtx); + ExpressionVector args = parseArguments(expCtx, bsonExpr, vps); expr->validateArguments(args); expr->vpOperand = args; return expr; } + +protected: + explicit ExpressionNaryBase(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionNary(expCtx) {} }; /// Inherit from this class if your expression takes a variable number of arguments. template <typename SubClass> -class ExpressionVariadic : public ExpressionNaryBase<SubClass> {}; +class ExpressionVariadic : public ExpressionNaryBase<SubClass> { +public: + explicit ExpressionVariadic(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionNaryBase<SubClass>(expCtx) {} +}; /** * Inherit from this class if your expression can take a range of arguments, e.g. if it has some @@ -379,6 +382,9 @@ class ExpressionVariadic : public ExpressionNaryBase<SubClass> {}; template <typename SubClass, int MinArgs, int MaxArgs> class ExpressionRangedArity : public ExpressionNaryBase<SubClass> { public: + explicit ExpressionRangedArity(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionNaryBase<SubClass>(expCtx) {} + void validateArguments(const Expression::ExpressionVector& args) const override { uassert(28667, mongoutils::str::stream() << "Expression " << this->getOpName() @@ -397,6 +403,9 @@ public: template <typename SubClass, int NArgs> class ExpressionFixedArity : public ExpressionNaryBase<SubClass> { public: + explicit ExpressionFixedArity(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionNaryBase<SubClass>(expCtx) {} + void validateArguments(const Expression::ExpressionVector& args) const override { uassert(16020, mongoutils::str::stream() << "Expression " << this->getOpName() << " takes exactly " @@ -416,9 +425,11 @@ template <typename Accumulator> class ExpressionFromAccumulator : public ExpressionVariadic<ExpressionFromAccumulator<Accumulator>> { public: + explicit ExpressionFromAccumulator(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionFromAccumulator<Accumulator>>(expCtx) {} + Value evaluateInternal(Variables* vars) const final { - Accumulator accum; - accum.injectExpressionContext(this->getExpressionContext()); + Accumulator accum(this->getExpressionContext()); const size_t n = this->vpOperand.size(); // If a single array arg is given, loop through it passing each member to the accumulator. // If a single, non-array arg is given, pass it directly to the accumulator. @@ -446,15 +457,15 @@ public: if (this->vpOperand.size() == 1) { return false; } - return Accumulator().isAssociative(); + return Accumulator(this->getExpressionContext()).isAssociative(); } bool isCommutative() const final { - return Accumulator().isCommutative(); + return Accumulator(this->getExpressionContext()).isCommutative(); } const char* getOpName() const final { - return Accumulator().getOpName(); + return Accumulator(this->getExpressionContext()).getOpName(); } }; @@ -464,6 +475,9 @@ public: template <typename SubClass> class ExpressionSingleNumericArg : public ExpressionFixedArity<SubClass, 1> { public: + explicit ExpressionSingleNumericArg(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<SubClass, 1>(expCtx) {} + virtual ~ExpressionSingleNumericArg() {} Value evaluateInternal(Variables* vars) const final { @@ -484,6 +498,10 @@ public: class ExpressionAbs final : public ExpressionSingleNumericArg<ExpressionAbs> { +public: + explicit ExpressionAbs(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionAbs>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -491,6 +509,9 @@ class ExpressionAbs final : public ExpressionSingleNumericArg<ExpressionAbs> { class ExpressionAdd final : public ExpressionVariadic<ExpressionAdd> { public: + explicit ExpressionAdd(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionAdd>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -506,6 +527,9 @@ public: class ExpressionAllElementsTrue final : public ExpressionFixedArity<ExpressionAllElementsTrue, 1> { public: + explicit ExpressionAllElementsTrue(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionAllElementsTrue, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -513,6 +537,9 @@ public: class ExpressionAnd final : public ExpressionVariadic<ExpressionAnd> { public: + explicit ExpressionAnd(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionAnd>(expCtx) {} + boost::intrusive_ptr<Expression> optimize() final; Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -529,6 +556,9 @@ public: class ExpressionAnyElementTrue final : public ExpressionFixedArity<ExpressionAnyElementTrue, 1> { public: + explicit ExpressionAnyElementTrue(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionAnyElementTrue, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -536,7 +566,9 @@ public: class ExpressionArray final : public ExpressionVariadic<ExpressionArray> { public: - // virtuals from ExpressionNary + explicit ExpressionArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionArray>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; Value serialize(bool explain) const final; const char* getOpName() const final; @@ -545,6 +577,9 @@ public: class ExpressionArrayElemAt final : public ExpressionFixedArity<ExpressionArrayElemAt, 2> { public: + explicit ExpressionArrayElemAt(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionArrayElemAt, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -552,6 +587,9 @@ public: class ExpressionCeil final : public ExpressionSingleNumericArg<ExpressionCeil> { public: + explicit ExpressionCeil(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionCeil>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -568,10 +606,9 @@ public: const boost::intrusive_ptr<ExpressionContext>& expCtx, const boost::intrusive_ptr<Expression>& pExpression); - void doInjectExpressionContext() final; - private: - explicit ExpressionCoerceToBool(const boost::intrusive_ptr<Expression>& pExpression); + ExpressionCoerceToBool(const boost::intrusive_ptr<ExpressionContext>& expCtx, + const boost::intrusive_ptr<Expression>& pExpression); boost::intrusive_ptr<Expression> pExpression; }; @@ -593,16 +630,20 @@ public: CMP = 6, // return -1, 0, 1 for a < b, a == b, a > b }; + ExpressionCompare(const boost::intrusive_ptr<ExpressionContext>& expCtx, CmpOp cmpOp) + : ExpressionFixedArity<ExpressionCompare, 2>(expCtx), cmpOp(cmpOp) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; - static boost::intrusive_ptr<Expression> parse(BSONElement bsonExpr, - const VariablesParseState& vps, - CmpOp cmpOp); - - explicit ExpressionCompare(CmpOp cmpOp); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps, + CmpOp cmpOp); static boost::intrusive_ptr<ExpressionCompare> create( + const boost::intrusive_ptr<ExpressionContext>& expCtx, CmpOp cmpOp, const boost::intrusive_ptr<Expression>& exprLeft, const boost::intrusive_ptr<Expression>& exprRight); @@ -614,6 +655,9 @@ private: class ExpressionConcat final : public ExpressionVariadic<ExpressionConcat> { public: + explicit ExpressionConcat(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionConcat>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -625,6 +669,9 @@ public: class ExpressionConcatArrays final : public ExpressionVariadic<ExpressionConcatArrays> { public: + explicit ExpressionConcatArrays(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionConcatArrays>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -635,13 +682,19 @@ public: class ExpressionCond final : public ExpressionFixedArity<ExpressionCond, 3> { - typedef ExpressionFixedArity<ExpressionCond, 3> Base; - public: + explicit ExpressionCond(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Base(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); + +private: + typedef ExpressionFixedArity<ExpressionCond, 3> Base; }; @@ -657,8 +710,10 @@ public: static boost::intrusive_ptr<ExpressionConstant> create( const boost::intrusive_ptr<ExpressionContext>& expCtx, const Value& pValue); - static boost::intrusive_ptr<Expression> parse(BSONElement bsonExpr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps); /* Get the constant value represented by this Expression. @@ -670,7 +725,7 @@ public: } private: - explicit ExpressionConstant(const Value& pValue); + ExpressionConstant(const boost::intrusive_ptr<ExpressionContext>& expCtx, const Value& pValue); Value pValue; }; @@ -682,12 +737,14 @@ public: Value evaluateInternal(Variables* vars) const final; void addDependencies(DepsTracker* deps) const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); - - void doInjectExpressionContext() final; + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); private: - ExpressionDateToString(const std::string& format, // the format string + ExpressionDateToString(const boost::intrusive_ptr<ExpressionContext>& expCtx, + const std::string& format, // the format string boost::intrusive_ptr<Expression> date); // the date to format // Will uassert on invalid data @@ -705,6 +762,9 @@ private: class ExpressionDayOfMonth final : public ExpressionFixedArity<ExpressionDayOfMonth, 1> { public: + explicit ExpressionDayOfMonth(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionDayOfMonth, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -716,6 +776,9 @@ public: class ExpressionDayOfWeek final : public ExpressionFixedArity<ExpressionDayOfWeek, 1> { public: + explicit ExpressionDayOfWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionDayOfWeek, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -728,6 +791,9 @@ public: class ExpressionDayOfYear final : public ExpressionFixedArity<ExpressionDayOfYear, 1> { public: + explicit ExpressionDayOfYear(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionDayOfYear, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -740,12 +806,19 @@ public: class ExpressionDivide final : public ExpressionFixedArity<ExpressionDivide, 2> { public: + explicit ExpressionDivide(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionDivide, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; class ExpressionExp final : public ExpressionSingleNumericArg<ExpressionExp> { +public: + explicit ExpressionExp(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionExp>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -771,18 +844,23 @@ public: indicator @returns the newly created field path expression */ - static boost::intrusive_ptr<ExpressionFieldPath> create(const std::string& fieldPath); + static boost::intrusive_ptr<ExpressionFieldPath> create( + const boost::intrusive_ptr<ExpressionContext>& expCtx, const std::string& fieldPath); /// Like create(), but works with the raw std::string from the user with the "$" prefixes. - static boost::intrusive_ptr<ExpressionFieldPath> parse(const std::string& raw, - const VariablesParseState& vps); + static boost::intrusive_ptr<ExpressionFieldPath> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + const std::string& raw, + const VariablesParseState& vps); const FieldPath& getFieldPath() const { return _fieldPath; } private: - ExpressionFieldPath(const std::string& fieldPath, Variables::Id variable); + ExpressionFieldPath(const boost::intrusive_ptr<ExpressionContext>& expCtx, + const std::string& fieldPath, + Variables::Id variable); /* Internal implementation of evaluateInternal(), used recursively. @@ -814,12 +892,14 @@ public: Value evaluateInternal(Variables* vars) const final; void addDependencies(DepsTracker* deps) const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); - - void doInjectExpressionContext() final; + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); private: - ExpressionFilter(std::string varName, + ExpressionFilter(const boost::intrusive_ptr<ExpressionContext>& expCtx, + std::string varName, Variables::Id varId, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> filter); @@ -837,6 +917,9 @@ private: class ExpressionFloor final : public ExpressionSingleNumericArg<ExpressionFloor> { public: + explicit ExpressionFloor(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionFloor>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -844,6 +927,9 @@ public: class ExpressionHour final : public ExpressionFixedArity<ExpressionHour, 1> { public: + explicit ExpressionHour(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionHour, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -855,6 +941,9 @@ public: class ExpressionIfNull final : public ExpressionFixedArity<ExpressionIfNull, 2> { public: + explicit ExpressionIfNull(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIfNull, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -862,6 +951,9 @@ public: class ExpressionIn final : public ExpressionFixedArity<ExpressionIn, 2> { public: + explicit ExpressionIn(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIn, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -869,6 +961,9 @@ public: class ExpressionIndexOfArray final : public ExpressionRangedArity<ExpressionIndexOfArray, 2, 4> { public: + explicit ExpressionIndexOfArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionRangedArity<ExpressionIndexOfArray, 2, 4>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -876,6 +971,9 @@ public: class ExpressionIndexOfBytes final : public ExpressionRangedArity<ExpressionIndexOfBytes, 2, 4> { public: + explicit ExpressionIndexOfBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionRangedArity<ExpressionIndexOfBytes, 2, 4>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -886,6 +984,9 @@ public: */ class ExpressionIndexOfCP final : public ExpressionRangedArity<ExpressionIndexOfCP, 2, 4> { public: + explicit ExpressionIndexOfCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionRangedArity<ExpressionIndexOfCP, 2, 4>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -898,9 +999,10 @@ public: Value evaluateInternal(Variables* vars) const final; void addDependencies(DepsTracker* deps) const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); - - void doInjectExpressionContext() final; + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); struct NameAndExpression { NameAndExpression() {} @@ -914,23 +1016,37 @@ public: typedef std::map<Variables::Id, NameAndExpression> VariableMap; private: - ExpressionLet(const VariableMap& vars, boost::intrusive_ptr<Expression> subExpression); + ExpressionLet(const boost::intrusive_ptr<ExpressionContext>& expCtx, + const VariableMap& vars, + boost::intrusive_ptr<Expression> subExpression); VariableMap _variables; boost::intrusive_ptr<Expression> _subExpression; }; class ExpressionLn final : public ExpressionSingleNumericArg<ExpressionLn> { +public: + explicit ExpressionLn(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionLn>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; class ExpressionLog final : public ExpressionFixedArity<ExpressionLog, 2> { +public: + explicit ExpressionLog(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionLog, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; class ExpressionLog10 final : public ExpressionSingleNumericArg<ExpressionLog10> { +public: + explicit ExpressionLog10(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionLog10>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -942,12 +1058,14 @@ public: Value evaluateInternal(Variables* vars) const final; void addDependencies(DepsTracker* deps) const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); - - void doInjectExpressionContext() final; + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); private: ExpressionMap( + const boost::intrusive_ptr<ExpressionContext>& expCtx, const std::string& varName, // name of variable to set Variables::Id varId, // id of variable to set boost::intrusive_ptr<Expression> input, // yields array to iterate @@ -965,7 +1083,10 @@ public: Value evaluateInternal(Variables* vars) const final; void addDependencies(DepsTracker* deps) const final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vps); private: enum MetaType { @@ -973,13 +1094,16 @@ private: RAND_VAL, }; - ExpressionMeta(MetaType metaType); + ExpressionMeta(const boost::intrusive_ptr<ExpressionContext>& expCtx, MetaType metaType); MetaType _metaType; }; class ExpressionMillisecond final : public ExpressionFixedArity<ExpressionMillisecond, 1> { public: + explicit ExpressionMillisecond(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionMillisecond, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -989,6 +1113,9 @@ public: class ExpressionMinute final : public ExpressionFixedArity<ExpressionMinute, 1> { public: + explicit ExpressionMinute(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionMinute, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1000,6 +1127,9 @@ public: class ExpressionMod final : public ExpressionFixedArity<ExpressionMod, 2> { public: + explicit ExpressionMod(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionMod, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1007,6 +1137,9 @@ public: class ExpressionMultiply final : public ExpressionVariadic<ExpressionMultiply> { public: + explicit ExpressionMultiply(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionMultiply>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1022,6 +1155,9 @@ public: class ExpressionMonth final : public ExpressionFixedArity<ExpressionMonth, 1> { public: + explicit ExpressionMonth(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionMonth, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1034,6 +1170,9 @@ public: class ExpressionNot final : public ExpressionFixedArity<ExpressionNot, 1> { public: + explicit ExpressionNot(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionNot, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1055,13 +1194,16 @@ public: Value serialize(bool explain) const final; static boost::intrusive_ptr<ExpressionObject> create( + const boost::intrusive_ptr<ExpressionContext>& expCtx, std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>>&& expressions); /** * Parses and constructs an ExpressionObject from 'obj'. */ - static boost::intrusive_ptr<ExpressionObject> parse(BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<ExpressionObject> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * This ExpressionObject must outlive the returned vector. @@ -1071,10 +1213,9 @@ public: return _expressions; } - void doInjectExpressionContext() final; - private: ExpressionObject( + const boost::intrusive_ptr<ExpressionContext>& expCtx, std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>>&& expressions); // The mapping from field name to expression within this object. This needs to respect the order @@ -1085,6 +1226,9 @@ private: class ExpressionOr final : public ExpressionVariadic<ExpressionOr> { public: + explicit ExpressionOr(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionOr>(expCtx) {} + boost::intrusive_ptr<Expression> optimize() final; Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1100,7 +1244,11 @@ public: class ExpressionPow final : public ExpressionFixedArity<ExpressionPow, 2> { public: - static boost::intrusive_ptr<Expression> create(Value base, Value exp); + explicit ExpressionPow(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionPow, 2>(expCtx) {} + + static boost::intrusive_ptr<Expression> create( + const boost::intrusive_ptr<ExpressionContext>& expCtx, Value base, Value exp); private: Value evaluateInternal(Variables* vars) const final; @@ -1109,6 +1257,10 @@ private: class ExpressionRange final : public ExpressionRangedArity<ExpressionRange, 2, 3> { +public: + explicit ExpressionRange(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionRangedArity<ExpressionRange, 2, 3>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1116,15 +1268,18 @@ class ExpressionRange final : public ExpressionRangedArity<ExpressionRange, 2, 3 class ExpressionReduce final : public Expression { public: + explicit ExpressionReduce(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : Expression(expCtx) {} + void addDependencies(DepsTracker* deps) const final; Value evaluateInternal(Variables* vars) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; - void doInjectExpressionContext() final; - private: boost::intrusive_ptr<Expression> _input; boost::intrusive_ptr<Expression> _initial; @@ -1137,6 +1292,9 @@ private: class ExpressionSecond final : public ExpressionFixedArity<ExpressionSecond, 1> { public: + explicit ExpressionSecond(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSecond, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1148,6 +1306,9 @@ public: class ExpressionSetDifference final : public ExpressionFixedArity<ExpressionSetDifference, 2> { public: + explicit ExpressionSetDifference(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSetDifference, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1155,6 +1316,9 @@ public: class ExpressionSetEquals final : public ExpressionVariadic<ExpressionSetEquals> { public: + explicit ExpressionSetEquals(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionSetEquals>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; void validateArguments(const ExpressionVector& args) const final; @@ -1163,6 +1327,9 @@ public: class ExpressionSetIntersection final : public ExpressionVariadic<ExpressionSetIntersection> { public: + explicit ExpressionSetIntersection(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionSetIntersection>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1179,6 +1346,9 @@ public: // Not final, inherited from for optimizations. class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> { public: + explicit ExpressionSetIsSubset(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSetIsSubset, 2>(expCtx) {} + boost::intrusive_ptr<Expression> optimize() override; Value evaluateInternal(Variables* vars) const override; const char* getOpName() const final; @@ -1190,7 +1360,9 @@ private: class ExpressionSetUnion final : public ExpressionVariadic<ExpressionSetUnion> { public: - // intrusive_ptr<Expression> optimize() final; + explicit ExpressionSetUnion(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionVariadic<ExpressionSetUnion>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1206,6 +1378,9 @@ public: class ExpressionSize final : public ExpressionFixedArity<ExpressionSize, 1> { public: + explicit ExpressionSize(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSize, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1213,6 +1388,9 @@ public: class ExpressionReverseArray final : public ExpressionFixedArity<ExpressionReverseArray, 1> { public: + explicit ExpressionReverseArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionReverseArray, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1220,6 +1398,9 @@ public: class ExpressionSlice final : public ExpressionRangedArity<ExpressionSlice, 2, 3> { public: + explicit ExpressionSlice(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionRangedArity<ExpressionSlice, 2, 3>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1227,6 +1408,9 @@ public: class ExpressionIsArray final : public ExpressionFixedArity<ExpressionIsArray, 1> { public: + explicit ExpressionIsArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIsArray, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1234,12 +1418,19 @@ public: class ExpressionSplit final : public ExpressionFixedArity<ExpressionSplit, 2> { public: + explicit ExpressionSplit(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSplit, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; class ExpressionSqrt final : public ExpressionSingleNumericArg<ExpressionSqrt> { +public: + explicit ExpressionSqrt(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionSqrt>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -1247,6 +1438,9 @@ class ExpressionSqrt final : public ExpressionSingleNumericArg<ExpressionSqrt> { class ExpressionStrcasecmp final : public ExpressionFixedArity<ExpressionStrcasecmp, 2> { public: + explicit ExpressionStrcasecmp(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionStrcasecmp, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1254,6 +1448,9 @@ public: class ExpressionSubstrBytes : public ExpressionFixedArity<ExpressionSubstrBytes, 3> { public: + explicit ExpressionSubstrBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSubstrBytes, 3>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const; }; @@ -1261,18 +1458,29 @@ public: class ExpressionSubstrCP final : public ExpressionFixedArity<ExpressionSubstrCP, 3> { public: + explicit ExpressionSubstrCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSubstrCP, 3>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; class ExpressionStrLenBytes final : public ExpressionFixedArity<ExpressionStrLenBytes, 1> { +public: + explicit ExpressionStrLenBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionStrLenBytes, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; class ExpressionStrLenCP final : public ExpressionFixedArity<ExpressionStrLenCP, 1> { +public: + explicit ExpressionStrLenCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionStrLenCP, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1280,6 +1488,9 @@ class ExpressionStrLenCP final : public ExpressionFixedArity<ExpressionStrLenCP, class ExpressionSubtract final : public ExpressionFixedArity<ExpressionSubtract, 2> { public: + explicit ExpressionSubtract(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionSubtract, 2>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1287,15 +1498,18 @@ public: class ExpressionSwitch final : public Expression { public: + explicit ExpressionSwitch(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : Expression(expCtx) {} + void addDependencies(DepsTracker* deps) const final; Value evaluateInternal(Variables* vars) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; - void doInjectExpressionContext() final; - private: using ExpressionPair = std::pair<boost::intrusive_ptr<Expression>, boost::intrusive_ptr<Expression>>; @@ -1307,6 +1521,9 @@ private: class ExpressionToLower final : public ExpressionFixedArity<ExpressionToLower, 1> { public: + explicit ExpressionToLower(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionToLower, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1314,6 +1531,9 @@ public: class ExpressionToUpper final : public ExpressionFixedArity<ExpressionToUpper, 1> { public: + explicit ExpressionToUpper(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionToUpper, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1321,6 +1541,9 @@ public: class ExpressionTrunc final : public ExpressionSingleNumericArg<ExpressionTrunc> { public: + explicit ExpressionTrunc(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionSingleNumericArg<ExpressionTrunc>(expCtx) {} + Value evaluateNumericArg(const Value& numericArg) const final; const char* getOpName() const final; }; @@ -1328,6 +1551,9 @@ public: class ExpressionType final : public ExpressionFixedArity<ExpressionType, 1> { public: + explicit ExpressionType(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionType, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; }; @@ -1335,6 +1561,9 @@ public: class ExpressionWeek final : public ExpressionFixedArity<ExpressionWeek, 1> { public: + explicit ExpressionWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionWeek, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1344,6 +1573,9 @@ public: class ExpressionIsoWeekYear final : public ExpressionFixedArity<ExpressionIsoWeekYear, 1> { public: + explicit ExpressionIsoWeekYear(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIsoWeekYear, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1353,6 +1585,9 @@ public: class ExpressionIsoDayOfWeek final : public ExpressionFixedArity<ExpressionIsoDayOfWeek, 1> { public: + explicit ExpressionIsoDayOfWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIsoDayOfWeek, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1362,6 +1597,9 @@ public: class ExpressionIsoWeek final : public ExpressionFixedArity<ExpressionIsoWeek, 1> { public: + explicit ExpressionIsoWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionIsoWeek, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1371,6 +1609,9 @@ public: class ExpressionYear final : public ExpressionFixedArity<ExpressionYear, 1> { public: + explicit ExpressionYear(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : ExpressionFixedArity<ExpressionYear, 1>(expCtx) {} + Value evaluateInternal(Variables* vars) const final; const char* getOpName() const final; @@ -1383,15 +1624,18 @@ public: class ExpressionZip final : public Expression { public: + explicit ExpressionZip(const boost::intrusive_ptr<ExpressionContext>& expCtx) + : Expression(expCtx) {} + void addDependencies(DepsTracker* deps) const final; Value evaluateInternal(Variables* vars) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse(BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse( + const boost::intrusive_ptr<ExpressionContext>& expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; - void doInjectExpressionContext() final; - private: bool _useLongestLength = false; ExpressionVector _inputs; |