diff options
Diffstat (limited to 'src/mongo/db/pipeline/expression.h')
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 104 |
1 files changed, 74 insertions, 30 deletions
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index ab82e3139e7..6532be87fb0 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -103,11 +103,17 @@ public: } /** - * Add the fields used as input to this expression to 'deps'. - * - * Expressions are trees, so this is often recursive. + * Add the fields and variables used in this expression to 'deps'. References to variables which + * are local to a particular expression will be filtered out of the tracker upon return. */ - virtual void addDependencies(DepsTracker* deps) const = 0; + void addDependencies(DepsTracker* deps) { + _doAddDependencies(deps); + + // Filter out references to any local variables. + if (_boundaryVariableId) { + deps->vars.erase(deps->vars.upper_bound(*_boundaryVariableId), deps->vars.end()); + } + } /** * Serialize the Expression tree recursively. @@ -205,7 +211,12 @@ public: static void registerExpression(std::string key, Parser parser); protected: - Expression(const boost::intrusive_ptr<ExpressionContext>& expCtx) : _expCtx(expCtx) {} + Expression(const boost::intrusive_ptr<ExpressionContext>& expCtx) : _expCtx(expCtx) { + auto varIds = _expCtx->variablesParseState.getDefinedVariableIDs(); + if (!varIds.empty()) { + _boundaryVariableId = *std::prev(varIds.end()); + } + } typedef std::vector<boost::intrusive_ptr<Expression>> ExpressionVector; @@ -213,17 +224,18 @@ protected: return _expCtx; } + virtual void _doAddDependencies(DepsTracker* deps) const = 0; + private: + boost::optional<Variables::Id> _boundaryVariableId; boost::intrusive_ptr<ExpressionContext> _expCtx; }; - -/// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class. +// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class. class ExpressionNary : public Expression { public: boost::intrusive_ptr<Expression> optimize() override; Value serialize(bool explain) const override; - void addDependencies(DepsTracker* deps) const override; /* Add an operand to the n-ary expression. @@ -260,6 +272,8 @@ protected: explicit ExpressionNary(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx) {} + void _doAddDependencies(DepsTracker* deps) const override; + ExpressionVector vpOperand; }; @@ -418,7 +432,6 @@ public: class ExpressionConstant final : public Expression { public: boost::intrusive_ptr<Expression> optimize() final; - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; Value serialize(bool explain) const final; @@ -461,6 +474,9 @@ public: return _value; } +protected: + void _doAddDependencies(DepsTracker* deps) const override; + private: ExpressionConstant(const boost::intrusive_ptr<ExpressionContext>& expCtx, const Value& value); @@ -504,13 +520,6 @@ public: return evaluateDate(date, timeZone); } - void addDependencies(DepsTracker* deps) const final { - _date->addDependencies(deps); - if (_timeZone) { - _timeZone->addDependencies(deps); - } - } - /** * Always serializes to the full {date: <date arg>, timezone: <timezone arg>} format, leaving * off the timezone if not specified. @@ -594,6 +603,13 @@ protected: const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx), _opName(opName) {} + void _doAddDependencies(DepsTracker* deps) const final { + _date->addDependencies(deps); + if (_timeZone) { + _timeZone->addDependencies(deps); + } + } + /** * Subclasses should implement this to do their actual date-related logic. Uses 'timezone' to * evaluate the expression against 'data'. If the user did not specify a time zone, 'timezone' @@ -729,7 +745,6 @@ public: class ExpressionCoerceToBool final : public Expression { public: boost::intrusive_ptr<Expression> optimize() final; - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; Value serialize(bool explain) const final; @@ -737,6 +752,9 @@ public: const boost::intrusive_ptr<ExpressionContext>& expCtx, const boost::intrusive_ptr<Expression>& pExpression); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionCoerceToBool(const boost::intrusive_ptr<ExpressionContext>& expCtx, const boost::intrusive_ptr<Expression>& pExpression); @@ -833,13 +851,15 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document&) const final; - void addDependencies(DepsTracker*) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionDateFromString(const boost::intrusive_ptr<ExpressionContext>& expCtx, boost::intrusive_ptr<Expression> dateString, @@ -854,13 +874,15 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionDateFromParts(const boost::intrusive_ptr<ExpressionContext>& expCtx, boost::intrusive_ptr<Expression> year, @@ -905,13 +927,15 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: /** * The iso8601 argument controls whether to output ISO8601 elements or natural calendar. @@ -933,13 +957,15 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionDateToString(const boost::intrusive_ptr<ExpressionContext>& expCtx, const std::string& format, // The format string. @@ -1007,7 +1033,6 @@ public: class ExpressionFieldPath final : public Expression { public: boost::intrusive_ptr<Expression> optimize() final; - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; Value serialize(bool explain) const final; @@ -1040,6 +1065,9 @@ public: ComputedPaths getComputedPaths(const std::string& exprFieldPath, Variables::Id renamingVar) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionFieldPath(const boost::intrusive_ptr<ExpressionContext>& expCtx, const std::string& fieldPath, @@ -1073,13 +1101,15 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionFilter(const boost::intrusive_ptr<ExpressionContext>& expCtx, std::string varName, @@ -1177,7 +1207,6 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, @@ -1195,6 +1224,9 @@ public: typedef std::map<Variables::Id, NameAndExpression> VariableMap; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionLet(const boost::intrusive_ptr<ExpressionContext>& expCtx, const VariableMap& vars, @@ -1236,7 +1268,6 @@ public: boost::intrusive_ptr<Expression> optimize() final; Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, @@ -1246,6 +1277,9 @@ public: ComputedPaths getComputedPaths(const std::string& exprFieldPath, Variables::Id renamingVar) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionMap( const boost::intrusive_ptr<ExpressionContext>& expCtx, @@ -1264,13 +1298,15 @@ class ExpressionMeta final : public Expression { public: Value serialize(bool explain) const final; Value evaluate(const Document& root) const final; - void addDependencies(DepsTracker* deps) const final; static boost::intrusive_ptr<Expression> parse( const boost::intrusive_ptr<ExpressionContext>& expCtx, BSONElement expr, const VariablesParseState& vps); +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: enum MetaType { TEXT_SCORE, @@ -1364,7 +1400,6 @@ public: class ExpressionObject final : public Expression { public: boost::intrusive_ptr<Expression> optimize() final; - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; Value serialize(bool explain) const final; @@ -1391,6 +1426,9 @@ public: ComputedPaths getComputedPaths(const std::string& exprFieldPath, Variables::Id renamingVar) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: ExpressionObject( const boost::intrusive_ptr<ExpressionContext>& expCtx, @@ -1449,7 +1487,6 @@ public: explicit ExpressionReduce(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx) {} - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; boost::intrusive_ptr<Expression> optimize() final; static boost::intrusive_ptr<Expression> parse( @@ -1458,6 +1495,9 @@ public: const VariablesParseState& vpsIn); Value serialize(bool explain) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: boost::intrusive_ptr<Expression> _input; boost::intrusive_ptr<Expression> _initial; @@ -1676,7 +1716,6 @@ public: explicit ExpressionSwitch(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx) {} - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; boost::intrusive_ptr<Expression> optimize() final; static boost::intrusive_ptr<Expression> parse( @@ -1685,6 +1724,9 @@ public: const VariablesParseState& vpsIn); Value serialize(bool explain) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: using ExpressionPair = std::pair<boost::intrusive_ptr<Expression>, boost::intrusive_ptr<Expression>>; @@ -1795,7 +1837,6 @@ public: explicit ExpressionZip(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx) {} - void addDependencies(DepsTracker* deps) const final; Value evaluate(const Document& root) const final; boost::intrusive_ptr<Expression> optimize() final; static boost::intrusive_ptr<Expression> parse( @@ -1804,6 +1845,9 @@ public: const VariablesParseState& vpsIn); Value serialize(bool explain) const final; +protected: + void _doAddDependencies(DepsTracker* deps) const final; + private: bool _useLongestLength = false; ExpressionVector _inputs; |