summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/expression.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/pipeline/expression.h')
-rw-r--r--src/mongo/db/pipeline/expression.h104
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;