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.h1675
1 files changed, 845 insertions, 830 deletions
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h
index 258e0d6c034..bec2013e2ff 100644
--- a/src/mongo/db/pipeline/expression.h
+++ b/src/mongo/db/pipeline/expression.h
@@ -42,1032 +42,1047 @@
namespace mongo {
- class BSONArrayBuilder;
- class BSONElement;
- class BSONObjBuilder;
- class DocumentSource;
-
- // TODO: Look into merging with ExpressionContext and possibly ObjectCtx.
- /// The state used as input and working space for Expressions.
- class Variables {
- MONGO_DISALLOW_COPYING(Variables);
- public:
- /**
- * Each unique variable is assigned a unique id of this type
- */
- typedef size_t Id;
-
- // This is only for expressions that use no variables (even ROOT).
- Variables() :_numVars(0) {}
-
- explicit Variables(size_t numVars, const Document& root = Document())
- : _root(root)
- , _rest(numVars == 0 ? NULL : new Value[numVars])
- , _numVars(numVars)
- {}
+class BSONArrayBuilder;
+class BSONElement;
+class BSONObjBuilder;
+class DocumentSource;
- static void uassertValidNameForUserWrite(StringData varName);
- static void uassertValidNameForUserRead(StringData varName);
+// TODO: Look into merging with ExpressionContext and possibly ObjectCtx.
+/// The state used as input and working space for Expressions.
+class Variables {
+ MONGO_DISALLOW_COPYING(Variables);
- static const Id ROOT_ID = Id(-1);
+public:
+ /**
+ * Each unique variable is assigned a unique id of this type
+ */
+ typedef size_t Id;
- /**
- * Use this instead of setValue for setting ROOT
- */
- void setRoot(const Document& root) { _root = root; }
- void clearRoot() { _root = Document(); }
- const Document& getRoot() const { return _root; }
+ // This is only for expressions that use no variables (even ROOT).
+ Variables() : _numVars(0) {}
- void setValue(Id id, const Value& value);
- Value getValue(Id id) const;
+ explicit Variables(size_t numVars, const Document& root = Document())
+ : _root(root), _rest(numVars == 0 ? NULL : new Value[numVars]), _numVars(numVars) {}
- /**
- * returns Document() for non-document values.
- */
- Document getDocument(Id id) const;
+ static void uassertValidNameForUserWrite(StringData varName);
+ static void uassertValidNameForUserRead(StringData varName);
- private:
- Document _root;
- const std::unique_ptr<Value[]> _rest;
- const size_t _numVars;
- };
+ static const Id ROOT_ID = Id(-1);
/**
- * Generates Variables::Ids and keeps track of the number of Ids handed out.
+ * Use this instead of setValue for setting ROOT
*/
- class VariablesIdGenerator {
- public:
- VariablesIdGenerator() : _nextId(0) {}
-
- Variables::Id generateId() { return _nextId++; }
-
- /**
- * Returns the number of Ids handed out by this Generator.
- * Return value is intended to be passed to Variables constructor.
- */
- Variables::Id getIdCount() const { return _nextId; }
+ void setRoot(const Document& root) {
+ _root = root;
+ }
+ void clearRoot() {
+ _root = Document();
+ }
+ const Document& getRoot() const {
+ return _root;
+ }
- private:
- Variables::Id _nextId;
- };
+ void setValue(Id id, const Value& value);
+ Value getValue(Id id) const;
/**
- * This class represents the Variables that are defined in an Expression tree.
- *
- * All copies from a given instance share enough information to ensure unique Ids are assigned
- * and to propagate back to the original instance enough information to correctly construct a
- * Variables instance.
+ * returns Document() for non-document values.
*/
- class VariablesParseState {
- public:
- explicit VariablesParseState(VariablesIdGenerator* idGenerator)
- : _idGenerator(idGenerator)
- {}
+ Document getDocument(Id id) const;
- /**
- * Assigns a named variable a unique Id. This differs from all other variables, even
- * others with the same name.
- *
- * The special variables ROOT and CURRENT are always implicitly defined with CURRENT
- * equivalent to ROOT. If CURRENT is explicitly defined by a call to this function, it
- * breaks that equivalence.
- *
- * NOTE: Name validation is responsibility of caller.
- */
- Variables::Id defineVariable(StringData name);
-
- /**
- * Returns the current Id for a variable. uasserts if the variable isn't defined.
- */
- Variables::Id getVariable(StringData name) const;
+private:
+ Document _root;
+ const std::unique_ptr<Value[]> _rest;
+ const size_t _numVars;
+};
- private:
- StringMap<Variables::Id> _variables;
- VariablesIdGenerator* _idGenerator;
- };
+/**
+ * Generates Variables::Ids and keeps track of the number of Ids handed out.
+ */
+class VariablesIdGenerator {
+public:
+ VariablesIdGenerator() : _nextId(0) {}
- class Expression :
- public IntrusiveCounterUnsigned {
- public:
- virtual ~Expression() {};
+ Variables::Id generateId() {
+ return _nextId++;
+ }
- /*
- Optimize the Expression.
+ /**
+ * Returns the number of Ids handed out by this Generator.
+ * Return value is intended to be passed to Variables constructor.
+ */
+ Variables::Id getIdCount() const {
+ return _nextId;
+ }
- This provides an opportunity to do constant folding, or to
- collapse nested operators that have the same precedence, such as
- $add, $and, or $or.
+private:
+ Variables::Id _nextId;
+};
- The Expression should be replaced with the return value, which may
- or may not be the same object. In the case of constant folding,
- a computed expression may be replaced by a constant.
+/**
+ * This class represents the Variables that are defined in an Expression tree.
+ *
+ * All copies from a given instance share enough information to ensure unique Ids are assigned
+ * and to propagate back to the original instance enough information to correctly construct a
+ * Variables instance.
+ */
+class VariablesParseState {
+public:
+ explicit VariablesParseState(VariablesIdGenerator* idGenerator) : _idGenerator(idGenerator) {}
- @returns the optimized Expression
- */
- virtual boost::intrusive_ptr<Expression> optimize() { return this; }
+ /**
+ * Assigns a named variable a unique Id. This differs from all other variables, even
+ * others with the same name.
+ *
+ * The special variables ROOT and CURRENT are always implicitly defined with CURRENT
+ * equivalent to ROOT. If CURRENT is explicitly defined by a call to this function, it
+ * breaks that equivalence.
+ *
+ * NOTE: Name validation is responsibility of caller.
+ */
+ Variables::Id defineVariable(StringData name);
- /**
- * Add this expression's field dependencies to the set
- *
- * Expressions are trees, so this is often recursive.
- *
- * @param deps Fully qualified paths to depended-on fields are added to this set.
- * Empty std::string means need full document.
- * @param path path to self if all ancestors are ExpressionObjects.
- * Top-level ExpressionObject gets pointer to empty vector.
- * If any other Expression is an ancestor, or in other cases
- * where {a:1} inclusion objects aren't allowed, they get
- * NULL.
- */
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const = 0;
+ /**
+ * Returns the current Id for a variable. uasserts if the variable isn't defined.
+ */
+ Variables::Id getVariable(StringData name) const;
- /** simple expressions are just inclusion exclusion as supported by ExpressionObject */
- virtual bool isSimple() { return false; }
+private:
+ StringMap<Variables::Id> _variables;
+ VariablesIdGenerator* _idGenerator;
+};
+class Expression : public IntrusiveCounterUnsigned {
+public:
+ virtual ~Expression(){};
- /**
- * Serialize the Expression tree recursively.
- * If explain is false, returns a Value parsable by parseOperand().
- */
- virtual Value serialize(bool explain) const = 0;
+ /*
+ Optimize the Expression.
- /// Evaluate expression with specified inputs and return result. (only used by tests)
- Value evaluate(const Document& root) const {
- Variables vars(0, root);
- return evaluate(&vars);
- }
+ This provides an opportunity to do constant folding, or to
+ collapse nested operators that have the same precedence, such as
+ $add, $and, or $or.
- /**
- * 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); }
+ The Expression should be replaced with the return value, which may
+ or may not be the same object. In the case of constant folding,
+ a computed expression may be replaced by a constant.
- /*
- Utility class for parseObject() below.
+ @returns the optimized Expression
+ */
+ virtual boost::intrusive_ptr<Expression> optimize() {
+ return this;
+ }
- DOCUMENT_OK indicates that it is OK to use a Document in the current
- context.
- */
- class ObjectCtx {
- public:
- ObjectCtx(int options);
- static const int DOCUMENT_OK = 0x0001;
- static const int TOP_LEVEL = 0x0002;
- static const int INCLUSION_OK = 0x0004;
-
- bool documentOk() const;
- bool topLevel() const;
- bool inclusionOk() const;
-
- private:
- int options;
- };
-
- //
- // Diagram of relationship between parse functions when parsing a $op:
- //
- // { someFieldOrArrayIndex: { $op: [ARGS] } }
- // ^ parseExpression on inner $op BSONElement
- // ^ parseObject on BSONObject
- // ^ parseOperand on outer BSONElement wrapping the $op Object
- //
+ /**
+ * Add this expression's field dependencies to the set
+ *
+ * Expressions are trees, so this is often recursive.
+ *
+ * @param deps Fully qualified paths to depended-on fields are added to this set.
+ * Empty std::string means need full document.
+ * @param path path to self if all ancestors are ExpressionObjects.
+ * Top-level ExpressionObject gets pointer to empty vector.
+ * If any other Expression is an ancestor, or in other cases
+ * where {a:1} inclusion objects aren't allowed, they get
+ * NULL.
+ */
+ virtual void addDependencies(DepsTracker* deps,
+ std::vector<std::string>* path = NULL) const = 0;
- /**
- * Parses a BSON Object that could represent a functional expression or a Document
- * expression.
- */
- static boost::intrusive_ptr<Expression> parseObject(
- BSONObj obj,
- ObjectCtx *pCtx,
- const VariablesParseState& vps);
+ /** simple expressions are just inclusion exclusion as supported by ExpressionObject */
+ virtual bool isSimple() {
+ return false;
+ }
- /**
- * Parses a BSONElement which has already been determined to be functional expression.
- *
- * exprElement should be the only element inside the expression object. That is the
- * field name should be the $op for the expression.
- */
- static boost::intrusive_ptr<Expression> parseExpression(
- BSONElement exprElement,
- const VariablesParseState& vps);
+ /**
+ * Serialize the Expression tree recursively.
+ * If explain is false, returns a Value parsable by parseOperand().
+ */
+ virtual Value serialize(bool explain) const = 0;
- /**
- * Parses a BSONElement which is an operand in an Expression.
- *
- * This is the most generic parser and can parse ExpressionFieldPath, a literal, or a $op.
- * If it is a $op, exprElement should be the outer element whose value is an Object
- * containing the $op.
- */
- static boost::intrusive_ptr<Expression> parseOperand(
- BSONElement exprElement,
- const VariablesParseState& vps);
+ /// Evaluate expression with specified inputs and return result. (only used by tests)
+ Value evaluate(const Document& root) const {
+ Variables vars(0, root);
+ return evaluate(&vars);
+ }
- /*
- Produce a field path std::string with the field prefix removed.
+ /**
+ * 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);
+ }
- Throws an error if the field prefix is not present.
+ /*
+ Utility class for parseObject() below.
- @param prefixedField the prefixed field
- @returns the field path with the prefix removed
- */
- static std::string removeFieldPrefix(const std::string &prefixedField);
+ DOCUMENT_OK indicates that it is OK to use a Document in the current
+ context.
+ */
+ class ObjectCtx {
+ public:
+ ObjectCtx(int options);
+ static const int DOCUMENT_OK = 0x0001;
+ static const int TOP_LEVEL = 0x0002;
+ static const int INCLUSION_OK = 0x0004;
- /** Evaluate the subclass Expression using the given Variables as context and return result.
- *
- * Should only be called by subclasses, but can't be protected because they need to call
- * this function on each other.
- */
- virtual Value evaluateInternal(Variables* vars) const = 0;
+ bool documentOk() const;
+ bool topLevel() const;
+ bool inclusionOk() const;
- protected:
- typedef std::vector<boost::intrusive_ptr<Expression> > ExpressionVector;
+ private:
+ int options;
};
+ //
+ // Diagram of relationship between parse functions when parsing a $op:
+ //
+ // { someFieldOrArrayIndex: { $op: [ARGS] } }
+ // ^ parseExpression on inner $op BSONElement
+ // ^ parseObject on BSONObject
+ // ^ parseOperand on outer BSONElement wrapping the $op Object
+ //
- /// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class.
- class ExpressionNary :
- public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value serialize(bool explain) const;
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
-
- /*
- Add an operand to the n-ary expression.
-
- @param pExpression the expression to add
- */
- virtual void addOperand(const boost::intrusive_ptr<Expression> &pExpression);
-
- // TODO split this into two functions
- virtual bool isAssociativeAndCommutative() const { return false; }
+ /**
+ * Parses a BSON Object that could represent a functional expression or a Document
+ * expression.
+ */
+ static boost::intrusive_ptr<Expression> parseObject(BSONObj obj,
+ ObjectCtx* pCtx,
+ const VariablesParseState& vps);
- /*
- Get the name of the operator.
+ /**
+ * Parses a BSONElement which has already been determined to be functional expression.
+ *
+ * exprElement should be the only element inside the expression object. That is the
+ * field name should be the $op for the expression.
+ */
+ static boost::intrusive_ptr<Expression> parseExpression(BSONElement exprElement,
+ const VariablesParseState& vps);
- @returns the name of the operator; this std::string belongs to the class
- implementation, and should not be deleted
- and should not
- */
- virtual const char* getOpName() const = 0;
- /// Allow subclasses the opportunity to validate arguments at parse time.
- virtual void validateArguments(const ExpressionVector& args) const {}
+ /**
+ * Parses a BSONElement which is an operand in an Expression.
+ *
+ * This is the most generic parser and can parse ExpressionFieldPath, a literal, or a $op.
+ * If it is a $op, exprElement should be the outer element whose value is an Object
+ * containing the $op.
+ */
+ static boost::intrusive_ptr<Expression> parseOperand(BSONElement exprElement,
+ const VariablesParseState& vps);
- static ExpressionVector parseArguments(
- BSONElement bsonExpr,
- const VariablesParseState& vps);
+ /*
+ Produce a field path std::string with the field prefix removed.
- protected:
- ExpressionNary() {}
+ Throws an error if the field prefix is not present.
- ExpressionVector vpOperand;
- };
+ @param prefixedField the prefixed field
+ @returns the field path with the prefix removed
+ */
+ static std::string removeFieldPrefix(const std::string& prefixedField);
- /// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class.
- 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);
- expr->validateArguments(args);
- expr->vpOperand = args;
- return expr;
- }
- };
+ /** Evaluate the subclass Expression using the given Variables as context and return result.
+ *
+ * Should only be called by subclasses, but can't be protected because they need to call
+ * this function on each other.
+ */
+ virtual Value evaluateInternal(Variables* vars) const = 0;
- /// Inherit from this class if your expression takes a variable number of arguments.
- template <typename SubClass>
- class ExpressionVariadic : public ExpressionNaryBase<SubClass> {
- };
+protected:
+ typedef std::vector<boost::intrusive_ptr<Expression>> ExpressionVector;
+};
- /// Inherit from this class if your expression takes a fixed number of arguments.
- template <typename SubClass, int NArgs>
- class ExpressionFixedArity : public ExpressionNaryBase<SubClass> {
- public:
- virtual void validateArguments(const Expression::ExpressionVector& args) const {
- uassert(16020, mongoutils::str::stream()
- << "Expression " << this->getOpName() << " takes exactly " << NArgs
- << " arguments. " << args.size() << " were passed in.",
- args.size() == NArgs);
-
- }
- };
+/// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class.
+class ExpressionNary : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value serialize(bool explain) const;
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
- class ExpressionAbs final : public ExpressionFixedArity<ExpressionAbs, 1> {
- Value evaluateInternal(Variables* vars) const final;
- const char* getOpName() const final;
- };
+ /*
+ Add an operand to the n-ary expression.
+ @param pExpression the expression to add
+ */
+ virtual void addOperand(const boost::intrusive_ptr<Expression>& pExpression);
- class ExpressionAdd : public ExpressionVariadic<ExpressionAdd> {
- public:
- // virtuals from Expression
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+ // TODO split this into two functions
+ virtual bool isAssociativeAndCommutative() const {
+ return false;
+ }
+ /*
+ Get the name of the operator.
+
+ @returns the name of the operator; this std::string belongs to the class
+ implementation, and should not be deleted
+ and should not
+ */
+ virtual const char* getOpName() const = 0;
+
+ /// 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);
+
+protected:
+ ExpressionNary() {}
+
+ ExpressionVector vpOperand;
+};
+
+/// Inherit from ExpressionVariadic or ExpressionFixedArity instead of directly from this class.
+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);
+ expr->validateArguments(args);
+ expr->vpOperand = args;
+ return expr;
+ }
+};
+
+/// Inherit from this class if your expression takes a variable number of arguments.
+template <typename SubClass>
+class ExpressionVariadic : public ExpressionNaryBase<SubClass> {};
+
+/// Inherit from this class if your expression takes a fixed number of arguments.
+template <typename SubClass, int NArgs>
+class ExpressionFixedArity : public ExpressionNaryBase<SubClass> {
+public:
+ virtual void validateArguments(const Expression::ExpressionVector& args) const {
+ uassert(16020,
+ mongoutils::str::stream() << "Expression " << this->getOpName() << " takes exactly "
+ << NArgs << " arguments. " << args.size()
+ << " were passed in.",
+ args.size() == NArgs);
+ }
+};
- class ExpressionAllElementsTrue : public ExpressionFixedArity<ExpressionAllElementsTrue, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionAbs final : public ExpressionFixedArity<ExpressionAbs, 1> {
+ Value evaluateInternal(Variables* vars) const final;
+ const char* getOpName() const final;
+};
- class ExpressionAnd : public ExpressionVariadic<ExpressionAnd> {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+class ExpressionAdd : public ExpressionVariadic<ExpressionAdd> {
+public:
+ // virtuals from Expression
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- class ExpressionAnyElementTrue : public ExpressionFixedArity<ExpressionAnyElementTrue, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionAllElementsTrue : public ExpressionFixedArity<ExpressionAllElementsTrue, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionArrayElemAt final : public ExpressionFixedArity<ExpressionArrayElemAt, 2> {
- public:
- Value evaluateInternal(Variables* vars) const final;
- const char* getOpName() const final;
- };
+class ExpressionAnd : public ExpressionVariadic<ExpressionAnd> {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- class ExpressionCoerceToBool : public Expression {
- public:
- // virtuals from ExpressionNary
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual Value serialize(bool explain) const;
- static boost::intrusive_ptr<ExpressionCoerceToBool> create(
- const boost::intrusive_ptr<Expression> &pExpression);
+class ExpressionAnyElementTrue : public ExpressionFixedArity<ExpressionAnyElementTrue, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- private:
- ExpressionCoerceToBool(const boost::intrusive_ptr<Expression> &pExpression);
+class ExpressionArrayElemAt final : public ExpressionFixedArity<ExpressionArrayElemAt, 2> {
+public:
+ Value evaluateInternal(Variables* vars) const final;
+ const char* getOpName() const final;
+};
- boost::intrusive_ptr<Expression> pExpression;
- };
+class ExpressionCoerceToBool : public Expression {
+public:
+ // virtuals from ExpressionNary
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual Value serialize(bool explain) const;
- class ExpressionCompare : public ExpressionFixedArity<ExpressionCompare, 2> {
- public:
+ static boost::intrusive_ptr<ExpressionCoerceToBool> create(
+ const boost::intrusive_ptr<Expression>& pExpression);
- /** Enumeration of comparison operators. Any changes to these values require adjustment of
- * the lookup table in the implementation.
- */
- enum CmpOp {
- EQ = 0, // return true for a == b, false otherwise
- NE = 1, // return true for a != b, false otherwise
- GT = 2, // return true for a > b, false otherwise
- GTE = 3, // return true for a >= b, false otherwise
- LT = 4, // return true for a < b, false otherwise
- LTE = 5, // return true for a <= b, false otherwise
- CMP = 6, // return -1, 0, 1 for a < b, a == b, a > b
- };
-
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
-
- static boost::intrusive_ptr<Expression> parse(
- BSONElement bsonExpr,
- const VariablesParseState& vps,
- CmpOp cmpOp);
-
- ExpressionCompare(CmpOp cmpOp);
- private:
- CmpOp cmpOp;
- };
+private:
+ ExpressionCoerceToBool(const boost::intrusive_ptr<Expression>& pExpression);
+ boost::intrusive_ptr<Expression> pExpression;
+};
- class ExpressionConcat : public ExpressionVariadic<ExpressionConcat> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
-
- class ExpressionConcatArrays final : public ExpressionVariadic<ExpressionConcatArrays> {
- public:
- Value evaluateInternal(Variables* vars) const final;
- const char* getOpName() const final;
+class ExpressionCompare : public ExpressionFixedArity<ExpressionCompare, 2> {
+public:
+ /** Enumeration of comparison operators. Any changes to these values require adjustment of
+ * the lookup table in the implementation.
+ */
+ enum CmpOp {
+ EQ = 0, // return true for a == b, false otherwise
+ NE = 1, // return true for a != b, false otherwise
+ GT = 2, // return true for a > b, false otherwise
+ GTE = 3, // return true for a >= b, false otherwise
+ LT = 4, // return true for a < b, false otherwise
+ LTE = 5, // return true for a <= b, false otherwise
+ CMP = 6, // return -1, 0, 1 for a < b, a == b, a > b
};
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- class ExpressionCond : public ExpressionFixedArity<ExpressionCond, 3> {
- typedef ExpressionFixedArity<ExpressionCond, 3> Base;
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+ static boost::intrusive_ptr<Expression> parse(BSONElement bsonExpr,
+ const VariablesParseState& vps,
+ CmpOp cmpOp);
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
- };
+ ExpressionCompare(CmpOp cmpOp);
+private:
+ CmpOp cmpOp;
+};
- class ExpressionConstant : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual Value serialize(bool explain) const;
-
- static boost::intrusive_ptr<ExpressionConstant> create(const Value& pValue);
- static boost::intrusive_ptr<Expression> parse(
- BSONElement bsonExpr,
- const VariablesParseState& vps);
-
- /*
- Get the constant value represented by this Expression.
-
- @returns the value
- */
- Value getValue() const;
- private:
- ExpressionConstant(const Value& pValue);
+class ExpressionConcat : public ExpressionVariadic<ExpressionConcat> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- Value pValue;
- };
- class ExpressionDateToString : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
+class ExpressionConcatArrays final : public ExpressionVariadic<ExpressionConcatArrays> {
+public:
+ Value evaluateInternal(Variables* vars) const final;
+ const char* getOpName() const final;
+};
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
- private:
- ExpressionDateToString(const std::string& format, // the format string
- boost::intrusive_ptr<Expression> date); // the date to format
+class ExpressionCond : public ExpressionFixedArity<ExpressionCond, 3> {
+ typedef ExpressionFixedArity<ExpressionCond, 3> Base;
- // Will uassert on invalid data
- static void validateFormat(const std::string& format);
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- // Need raw date as tm doesn't have millisecond resolution.
- // Format must be valid.
- static std::string formatDate(const std::string& format,
- const tm& tm,
- const long long date);
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
+};
- static void insertPadded(StringBuilder& sb, int number, int spaces);
- const std::string _format;
- boost::intrusive_ptr<Expression> _date;
- };
+class ExpressionConstant : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual Value serialize(bool explain) const;
- class ExpressionDayOfMonth : public ExpressionFixedArity<ExpressionDayOfMonth, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+ static boost::intrusive_ptr<ExpressionConstant> create(const Value& pValue);
+ static boost::intrusive_ptr<Expression> parse(BSONElement bsonExpr,
+ const VariablesParseState& vps);
- static inline int extract(const tm& tm) { return tm.tm_mday; }
- };
+ /*
+ Get the constant value represented by this Expression.
+ @returns the value
+ */
+ Value getValue() const;
- class ExpressionDayOfWeek : public ExpressionFixedArity<ExpressionDayOfWeek, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+private:
+ ExpressionConstant(const Value& pValue);
- // MySQL uses 1-7, tm uses 0-6
- static inline int extract(const tm& tm) { return tm.tm_wday + 1; }
- };
+ Value pValue;
+};
+class ExpressionDateToString : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value serialize(bool explain) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
- class ExpressionDayOfYear : public ExpressionFixedArity<ExpressionDayOfYear, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
- // MySQL uses 1-366, tm uses 0-365
- static inline int extract(const tm& tm) { return tm.tm_yday + 1; }
- };
+private:
+ ExpressionDateToString(const std::string& format, // the format string
+ boost::intrusive_ptr<Expression> date); // the date to format
+ // Will uassert on invalid data
+ static void validateFormat(const std::string& format);
- class ExpressionDivide : public ExpressionFixedArity<ExpressionDivide, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+ // Need raw date as tm doesn't have millisecond resolution.
+ // Format must be valid.
+ static std::string formatDate(const std::string& format, const tm& tm, const long long date);
+ static void insertPadded(StringBuilder& sb, int number, int spaces);
- class ExpressionFieldPath : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual Value serialize(bool explain) const;
+ const std::string _format;
+ boost::intrusive_ptr<Expression> _date;
+};
- /*
- Create a field path expression using old semantics (rooted off of CURRENT).
+class ExpressionDayOfMonth : public ExpressionFixedArity<ExpressionDayOfMonth, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- // NOTE: this method is deprecated and only used by tests
- // TODO remove this method in favor of parse()
+ static inline int extract(const tm& tm) {
+ return tm.tm_mday;
+ }
+};
- Evaluation will extract the value associated with the given field
- path from the source document.
- @param fieldPath the field path string, without any leading document
- indicator
- @returns the newly created field path expression
- */
- static boost::intrusive_ptr<ExpressionFieldPath> create(const std::string& fieldPath);
+class ExpressionDayOfWeek : public ExpressionFixedArity<ExpressionDayOfWeek, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- /// 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);
+ // MySQL uses 1-7, tm uses 0-6
+ static inline int extract(const tm& tm) {
+ return tm.tm_wday + 1;
+ }
+};
- const FieldPath& getFieldPath() const { return _fieldPath; }
- private:
- ExpressionFieldPath(const std::string& fieldPath, Variables::Id variable);
+class ExpressionDayOfYear : public ExpressionFixedArity<ExpressionDayOfYear, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- /*
- Internal implementation of evaluateInternal(), used recursively.
+ // MySQL uses 1-366, tm uses 0-365
+ static inline int extract(const tm& tm) {
+ return tm.tm_yday + 1;
+ }
+};
- The internal implementation doesn't just use a loop because of
- the possibility that we need to skip over an array. If the path
- is "a.b.c", and a is an array, then we fan out from there, and
- traverse "b.c" for each element of a:[...]. This requires that
- a be an array of objects in order to navigate more deeply.
- @param index current path field index to extract
- @param input current document traversed to (not the top-level one)
- @returns the field found; could be an array
- */
- Value evaluatePath(size_t index, const Document& input) const;
+class ExpressionDivide : public ExpressionFixedArity<ExpressionDivide, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- // Helper for evaluatePath to handle Array case
- Value evaluatePathArray(size_t index, const Value& input) const;
- const FieldPath _fieldPath;
- const Variables::Id _variable;
- };
+class ExpressionFieldPath : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual Value serialize(bool explain) const;
+ /*
+ Create a field path expression using old semantics (rooted off of CURRENT).
- class ExpressionFilter final : public Expression {
- public:
- // virtuals from Expression
- boost::intrusive_ptr<Expression> optimize() final;
- Value serialize(bool explain) const final;
- Value evaluateInternal(Variables* vars) const final;
- void addDependencies(DepsTracker* deps,
- std::vector<std::string>* path=NULL) const final;
+ // NOTE: this method is deprecated and only used by tests
+ // TODO remove this method in favor of parse()
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
+ Evaluation will extract the value associated with the given field
+ path from the source document.
- private:
- ExpressionFilter(std::string varName,
- Variables::Id varId,
- boost::intrusive_ptr<Expression> input,
- boost::intrusive_ptr<Expression> filter);
-
- // The name of the variable to set to each element in the array.
- std::string _varName;
- // The id of the variable to set.
- Variables::Id _varId;
- // The array to iterate over.
- boost::intrusive_ptr<Expression> _input;
- // The expression determining whether each element should be present in the result array.
- boost::intrusive_ptr<Expression> _filter;
- };
-
-
- class ExpressionHour : public ExpressionFixedArity<ExpressionHour, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
-
- static inline int extract(const tm& tm) { return tm.tm_hour; }
- };
+ @param fieldPath the field path string, without any leading document
+ indicator
+ @returns the newly created field path expression
+ */
+ static boost::intrusive_ptr<ExpressionFieldPath> create(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);
- class ExpressionIfNull : public ExpressionFixedArity<ExpressionIfNull, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+ const FieldPath& getFieldPath() const {
+ return _fieldPath;
+ }
+private:
+ ExpressionFieldPath(const std::string& fieldPath, Variables::Id variable);
- class ExpressionLet : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
+ /*
+ Internal implementation of evaluateInternal(), used recursively.
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
+ The internal implementation doesn't just use a loop because of
+ the possibility that we need to skip over an array. If the path
+ is "a.b.c", and a is an array, then we fan out from there, and
+ traverse "b.c" for each element of a:[...]. This requires that
+ a be an array of objects in order to navigate more deeply.
- struct NameAndExpression {
- NameAndExpression() {}
- NameAndExpression(std::string name, boost::intrusive_ptr<Expression> expression)
- : name(name)
- , expression(expression)
- {}
+ @param index current path field index to extract
+ @param input current document traversed to (not the top-level one)
+ @returns the field found; could be an array
+ */
+ Value evaluatePath(size_t index, const Document& input) const;
+
+ // Helper for evaluatePath to handle Array case
+ Value evaluatePathArray(size_t index, const Value& input) const;
+
+ const FieldPath _fieldPath;
+ const Variables::Id _variable;
+};
+
+
+class ExpressionFilter final : public Expression {
+public:
+ // virtuals from Expression
+ boost::intrusive_ptr<Expression> optimize() final;
+ Value serialize(bool explain) const final;
+ Value evaluateInternal(Variables* vars) const final;
+ void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const final;
+
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
+
+private:
+ ExpressionFilter(std::string varName,
+ Variables::Id varId,
+ boost::intrusive_ptr<Expression> input,
+ boost::intrusive_ptr<Expression> filter);
+
+ // The name of the variable to set to each element in the array.
+ std::string _varName;
+ // The id of the variable to set.
+ Variables::Id _varId;
+ // The array to iterate over.
+ boost::intrusive_ptr<Expression> _input;
+ // The expression determining whether each element should be present in the result array.
+ boost::intrusive_ptr<Expression> _filter;
+};
+
+
+class ExpressionHour : public ExpressionFixedArity<ExpressionHour, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+
+ static inline int extract(const tm& tm) {
+ return tm.tm_hour;
+ }
+};
- std::string name;
- boost::intrusive_ptr<Expression> expression;
- };
- typedef std::map<Variables::Id, NameAndExpression> VariableMap;
+class ExpressionIfNull : public ExpressionFixedArity<ExpressionIfNull, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- private:
- ExpressionLet(const VariableMap& vars,
- boost::intrusive_ptr<Expression> subExpression);
- VariableMap _variables;
- boost::intrusive_ptr<Expression> _subExpression;
- };
+class ExpressionLet : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value serialize(bool explain) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
- class ExpressionMap : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
+ struct NameAndExpression {
+ NameAndExpression() {}
+ NameAndExpression(std::string name, boost::intrusive_ptr<Expression> expression)
+ : name(name), expression(expression) {}
- private:
- ExpressionMap(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
- boost::intrusive_ptr<Expression> each); // yields results to be added to output array
-
- std::string _varName;
- Variables::Id _varId;
- boost::intrusive_ptr<Expression> _input;
- boost::intrusive_ptr<Expression> _each;
+ std::string name;
+ boost::intrusive_ptr<Expression> expression;
};
- class ExpressionMeta : public Expression {
- public:
- // virtuals from Expression
- virtual Value serialize(bool explain) const;
- virtual Value evaluateInternal(Variables* vars) const;
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
-
- static boost::intrusive_ptr<Expression> parse(
- BSONElement expr,
- const VariablesParseState& vps);
- };
+ typedef std::map<Variables::Id, NameAndExpression> VariableMap;
+
+private:
+ ExpressionLet(const VariableMap& vars, boost::intrusive_ptr<Expression> subExpression);
+
+ VariableMap _variables;
+ boost::intrusive_ptr<Expression> _subExpression;
+};
+
+class ExpressionMap : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value serialize(bool explain) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
+
+private:
+ ExpressionMap(
+ 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
+ boost::intrusive_ptr<Expression> each); // yields results to be added to output array
+
+ std::string _varName;
+ Variables::Id _varId;
+ boost::intrusive_ptr<Expression> _input;
+ boost::intrusive_ptr<Expression> _each;
+};
+
+class ExpressionMeta : public Expression {
+public:
+ // virtuals from Expression
+ virtual Value serialize(bool explain) const;
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+
+ static boost::intrusive_ptr<Expression> parse(BSONElement expr, const VariablesParseState& vps);
+};
+
+class ExpressionMillisecond : public ExpressionFixedArity<ExpressionMillisecond, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+
+ static int extract(const long long date);
+};
+
+
+class ExpressionMinute : public ExpressionFixedArity<ExpressionMinute, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+
+ static int extract(const tm& tm) {
+ return tm.tm_min;
+ }
+};
- class ExpressionMillisecond : public ExpressionFixedArity<ExpressionMillisecond, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- static int extract(const long long date);
- };
+class ExpressionMod : public ExpressionFixedArity<ExpressionMod, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionMinute : public ExpressionFixedArity<ExpressionMinute, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+class ExpressionMultiply : public ExpressionVariadic<ExpressionMultiply> {
+public:
+ // virtuals from Expression
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- static int extract(const tm& tm) { return tm.tm_min; }
- };
+class ExpressionMonth : public ExpressionFixedArity<ExpressionMonth, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- class ExpressionMod : public ExpressionFixedArity<ExpressionMod, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
-
+ // MySQL uses 1-12, tm uses 0-11
+ static inline int extract(const tm& tm) {
+ return tm.tm_mon + 1;
+ }
+};
- class ExpressionMultiply : public ExpressionVariadic<ExpressionMultiply> {
- public:
- // virtuals from Expression
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+class ExpressionNot : public ExpressionFixedArity<ExpressionNot, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionMonth : public ExpressionFixedArity<ExpressionMonth, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- // MySQL uses 1-12, tm uses 0-11
- static inline int extract(const tm& tm) { return tm.tm_mon + 1; }
- };
+class ExpressionObject : public Expression {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual bool isSimple();
+ virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path = NULL) const;
+ /** Only evaluates non inclusion expressions. For inclusions, use addToDocument(). */
+ 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(Variables* vars) const;
- class ExpressionNot : public ExpressionFixedArity<ExpressionNot, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+ /** Evaluates with inclusions and adds results to passed in Mutable document
+ *
+ * @param output the MutableDocument to add the evaluated expressions to
+ * @param currentDoc the input Document for this level (for inclusions)
+ * @param vars the variables for use in subexpressions
+ */
+ void addToDocument(MutableDocument& ouput, const Document& currentDoc, Variables* vars) const;
+ // estimated number of fields that will be output
+ size_t getSizeHint() const;
- class ExpressionObject : public Expression {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual bool isSimple();
- virtual void addDependencies(DepsTracker* deps, std::vector<std::string>* path=NULL) const;
- /** Only evaluates non inclusion expressions. For inclusions, use addToDocument(). */
- 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(Variables* vars) const;
-
- /** Evaluates with inclusions and adds results to passed in Mutable document
- *
- * @param output the MutableDocument to add the evaluated expressions to
- * @param currentDoc the input Document for this level (for inclusions)
- * @param vars the variables for use in subexpressions
- */
- void addToDocument(MutableDocument& ouput,
- const Document& currentDoc,
- Variables* vars
- ) const;
+ /** Create an empty expression.
+ * Until fields are added, this will evaluate to an empty document.
+ */
+ static boost::intrusive_ptr<ExpressionObject> create();
- // estimated number of fields that will be output
- size_t getSizeHint() const;
+ /// Like create but uses special handling of _id for root object of $project.
+ static boost::intrusive_ptr<ExpressionObject> createRoot();
- /** Create an empty expression.
- * Until fields are added, this will evaluate to an empty document.
- */
- static boost::intrusive_ptr<ExpressionObject> create();
+ /*
+ Add a field to the document expression.
- /// Like create but uses special handling of _id for root object of $project.
- static boost::intrusive_ptr<ExpressionObject> createRoot();
+ @param fieldPath the path the evaluated expression will have in the
+ result Document
+ @param pExpression the expression to evaluate obtain this field's
+ Value in the result Document
+ */
+ void addField(const FieldPath& fieldPath, const boost::intrusive_ptr<Expression>& pExpression);
- /*
- Add a field to the document expression.
+ /*
+ Add a field path to the set of those to be included.
- @param fieldPath the path the evaluated expression will have in the
- result Document
- @param pExpression the expression to evaluate obtain this field's
- Value in the result Document
- */
- void addField(const FieldPath &fieldPath,
- const boost::intrusive_ptr<Expression> &pExpression);
+ Note that including a nested field implies including everything on
+ the path leading down to it.
- /*
- Add a field path to the set of those to be included.
+ @param fieldPath the name of the field to be included
+ */
+ void includePath(const std::string& fieldPath);
- Note that including a nested field implies including everything on
- the path leading down to it.
+ /*
+ Get a count of the added fields.
- @param fieldPath the name of the field to be included
- */
- void includePath(const std::string &fieldPath);
+ @returns how many fields have been added
+ */
+ size_t getFieldCount() const;
- /*
- Get a count of the added fields.
+ /*
+ Specialized BSON conversion that allows for writing out a
+ $project specification. This creates a standalone object, which must
+ be added to a containing object with a name
- @returns how many fields have been added
- */
- size_t getFieldCount() const;
+ @param pBuilder where to write the object to
+ @param requireExpression see Expression::addToBsonObj
+ */
+ void documentToBson(BSONObjBuilder* pBuilder, bool requireExpression) const;
- /*
- Specialized BSON conversion that allows for writing out a
- $project specification. This creates a standalone object, which must
- be added to a containing object with a name
+ /*
+ Visitor abstraction used by emitPaths(). Each path is recorded by
+ calling path().
+ */
+ class PathSink {
+ public:
+ virtual ~PathSink(){};
- @param pBuilder where to write the object to
- @param requireExpression see Expression::addToBsonObj
- */
- void documentToBson(BSONObjBuilder *pBuilder,
- bool requireExpression) const;
+ /**
+ Record a path.
- /*
- Visitor abstraction used by emitPaths(). Each path is recorded by
- calling path().
+ @param path the dotted path string
+ @param include if true, the path is included; if false, the path
+ is excluded
*/
- class PathSink {
- public:
- virtual ~PathSink() {};
-
- /**
- Record a path.
+ virtual void path(const std::string& path, bool include) = 0;
+ };
- @param path the dotted path string
- @param include if true, the path is included; if false, the path
- is excluded
- */
- virtual void path(const std::string &path, bool include) = 0;
- };
+ void excludeId(bool b) {
+ _excludeId = b;
+ }
- void excludeId(bool b) { _excludeId = b; }
+private:
+ ExpressionObject(bool atRoot);
- private:
- ExpressionObject(bool atRoot);
+ // Mapping from fieldname to the Expression that generates its value.
+ // NULL expression means inclusion from source document.
+ typedef std::map<std::string, boost::intrusive_ptr<Expression>> FieldMap;
+ FieldMap _expressions;
- // Mapping from fieldname to the Expression that generates its value.
- // NULL expression means inclusion from source document.
- typedef std::map<std::string, boost::intrusive_ptr<Expression> > FieldMap;
- FieldMap _expressions;
+ // this is used to maintain order for generated fields not in the source document
+ std::vector<std::string> _order;
- // this is used to maintain order for generated fields not in the source document
- std::vector<std::string> _order;
+ bool _excludeId;
+ bool _atRoot;
+};
- bool _excludeId;
- bool _atRoot;
- };
+class ExpressionOr : public ExpressionVariadic<ExpressionOr> {
+public:
+ // virtuals from Expression
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- class ExpressionOr : public ExpressionVariadic<ExpressionOr> {
- public:
- // virtuals from Expression
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+class ExpressionSecond : public ExpressionFixedArity<ExpressionSecond, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- class ExpressionSecond : public ExpressionFixedArity<ExpressionSecond, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+ static inline int extract(const tm& tm) {
+ return tm.tm_sec;
+ }
+};
- static inline int extract(const tm& tm) { return tm.tm_sec; }
- };
+class ExpressionSetDifference : public ExpressionFixedArity<ExpressionSetDifference, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionSetDifference : public ExpressionFixedArity<ExpressionSetDifference, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionSetEquals : public ExpressionVariadic<ExpressionSetEquals> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual void validateArguments(const ExpressionVector& args) const;
+};
- class ExpressionSetEquals : public ExpressionVariadic<ExpressionSetEquals> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual void validateArguments(const ExpressionVector& args) const;
- };
+class ExpressionSetIntersection : public ExpressionVariadic<ExpressionSetIntersection> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- class ExpressionSetIntersection : public ExpressionVariadic<ExpressionSetIntersection> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual boost::intrusive_ptr<Expression> optimize();
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> {
- public:
- // virtuals from ExpressionNary
- virtual boost::intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- private:
- class Optimized;
- };
+private:
+ class Optimized;
+};
- class ExpressionSetUnion : public ExpressionVariadic<ExpressionSetUnion> {
- public:
- // virtuals from ExpressionNary
- // virtual intrusive_ptr<Expression> optimize();
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- virtual bool isAssociativeAndCommutative() const { return true; }
- };
+class ExpressionSetUnion : public ExpressionVariadic<ExpressionSetUnion> {
+public:
+ // virtuals from ExpressionNary
+ // virtual intrusive_ptr<Expression> optimize();
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+ virtual bool isAssociativeAndCommutative() const {
+ return true;
+ }
+};
- class ExpressionIsArray : public ExpressionFixedArity<ExpressionIsArray, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionIsArray : public ExpressionFixedArity<ExpressionIsArray, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionSize : public ExpressionFixedArity<ExpressionSize, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionSize : public ExpressionFixedArity<ExpressionSize, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionStrcasecmp : public ExpressionFixedArity<ExpressionStrcasecmp, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionStrcasecmp : public ExpressionFixedArity<ExpressionStrcasecmp, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionSubstr : public ExpressionFixedArity<ExpressionSubstr, 3> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionSubstr : public ExpressionFixedArity<ExpressionSubstr, 3> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionSubtract : public ExpressionFixedArity<ExpressionSubtract, 2> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionSubtract : public ExpressionFixedArity<ExpressionSubtract, 2> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionToLower : public ExpressionFixedArity<ExpressionToLower, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionToLower : public ExpressionFixedArity<ExpressionToLower, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionToUpper : public ExpressionFixedArity<ExpressionToUpper, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
- };
+class ExpressionToUpper : public ExpressionFixedArity<ExpressionToUpper, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
+};
- class ExpressionWeek : public ExpressionFixedArity<ExpressionWeek, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+class ExpressionWeek : public ExpressionFixedArity<ExpressionWeek, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- static int extract(const tm& tm);
- };
+ static int extract(const tm& tm);
+};
- class ExpressionYear : public ExpressionFixedArity<ExpressionYear, 1> {
- public:
- // virtuals from ExpressionNary
- virtual Value evaluateInternal(Variables* vars) const;
- virtual const char* getOpName() const;
+class ExpressionYear : public ExpressionFixedArity<ExpressionYear, 1> {
+public:
+ // virtuals from ExpressionNary
+ virtual Value evaluateInternal(Variables* vars) const;
+ virtual const char* getOpName() const;
- // tm_year is years since 1990
- static int extract(const tm& tm) { return tm.tm_year + 1900; }
- };
+ // tm_year is years since 1990
+ static int extract(const tm& tm) {
+ return tm.tm_year + 1900;
+ }
+};
}
@@ -1075,11 +1090,11 @@ namespace mongo {
namespace mongo {
- inline Value ExpressionConstant::getValue() const {
- return pValue;
- }
+inline Value ExpressionConstant::getValue() const {
+ return pValue;
+}
- inline size_t ExpressionObject::getFieldCount() const {
- return _expressions.size();
- }
+inline size_t ExpressionObject::getFieldCount() const {
+ return _expressions.size();
+}
}