diff options
40 files changed, 1480 insertions, 667 deletions
diff --git a/jstests/aggregation/sources/lookup/lookup.js b/jstests/aggregation/sources/lookup/lookup.js index b93691aa27f..def8cadfd42 100644 --- a/jstests/aggregation/sources/lookup/lookup.js +++ b/jstests/aggregation/sources/lookup/lookup.js @@ -463,7 +463,7 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode. assert.writeOK(from.insert({_id: 2})); assert.writeOK(from.insert({_id: 3})); - // Basic non-equi theta join. + // Basic non-equi theta join via $project. pipeline = [ { $lookup: { @@ -495,6 +495,90 @@ load("jstests/aggregation/extras/utils.js"); // For assertErrorCode. ]; testPipeline(pipeline, expectedResults, coll); + // Basic non-equi theta join via $match. + pipeline = [ + { + $lookup: { + let : {var1: "$_id"}, + pipeline: [ + {$match: {_id: {$lt: {$expr: "$$var1"}}}}, + ], + from: "from", + as: "c", + } + }, + ]; + + expectedResults = [ + {"_id": 1, x: 1, "c": []}, + {"_id": 2, x: 2, "c": [{"_id": 1}]}, + { + "_id": 3, + x: 3, + "c": [ + {"_id": 1}, + { + "_id": 2, + } + ] + } + ]; + testPipeline(pipeline, expectedResults, coll); + + // Multi-level join using $match. + pipeline = [ + { + $lookup: { + let : {var1: "$_id"}, + pipeline: [ + {$match: {_id: {$eq: {$expr: "$$var1"}}}}, + { + $lookup: { + let : {var2: "$_id"}, + pipeline: [ + {$match: {_id: {$gt: {$expr: "$$var2"}}}}, + ], + from: "from", + as: "d" + } + }, + ], + from: "from", + as: "c", + } + }, + ]; + + expectedResults = [ + {"_id": 1, "x": 1, "c": [{"_id": 1, "d": [{"_id": 2}, {"_id": 3}]}]}, + {"_id": 2, "x": 2, "c": [{"_id": 2, "d": [{"_id": 3}]}]}, + {"_id": 3, "x": 3, "c": [{"_id": 3, "d": []}]} + ]; + testPipeline(pipeline, expectedResults, coll); + + // Equijoin with $match that can't be delegated to the query subsystem. + pipeline = [ + { + $lookup: { + let : {var1: "$x"}, + pipeline: [ + {$addFields: {newField: 2}}, + {$match: {newField: {$expr: "$$var1"}}}, + {$project: {newField: 0}} + ], + from: "from", + as: "c", + } + }, + ]; + + expectedResults = [ + {"_id": 1, "x": 1, "c": []}, + {"_id": 2, "x": 2, "c": [{"_id": 1}, {"_id": 2}, {"_id": 3}]}, + {"_id": 3, "x": 3, "c": []} + ]; + testPipeline(pipeline, expectedResults, coll); + // Multiple variables. pipeline = [ { diff --git a/jstests/aggregation/variables/layered_variables.js b/jstests/aggregation/variables/layered_variables.js index 5e5f2f94c05..e0e10494b29 100644 --- a/jstests/aggregation/variables/layered_variables.js +++ b/jstests/aggregation/variables/layered_variables.js @@ -53,5 +53,6 @@ assert.eq( {_id: 1, has_permissions: 1, my_array: [2, 3], a: 1, b: 6, c: [2, 3], d: 3000, e: [3, 4]}, - res.cursor.firstBatch[0]); + res.cursor.firstBatch[0], + tojson(res)); })(); diff --git a/src/mongo/db/matcher/SConscript b/src/mongo/db/matcher/SConscript index fe025b6b8ad..4f7af21e9a1 100644 --- a/src/mongo/db/matcher/SConscript +++ b/src/mongo/db/matcher/SConscript @@ -66,6 +66,7 @@ env.Library( '$BUILD_DIR/mongo/db/geo/geometry', '$BUILD_DIR/mongo/db/geo/geoparser', '$BUILD_DIR/mongo/db/query/collation/collator_interface', + '$BUILD_DIR/mongo/db/pipeline/expression', '$BUILD_DIR/third_party/shim_pcrecpp', 'path', ], diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp index 4a0a4598927..5b995614df0 100644 --- a/src/mongo/db/matcher/expression_leaf.cpp +++ b/src/mongo/db/matcher/expression_leaf.cpp @@ -59,18 +59,15 @@ bool ComparisonMatchExpression::equivalent(const MatchExpression* other) const { const StringData::ComparatorInterface* stringComparator = nullptr; BSONElementComparator eltCmp(BSONElementComparator::FieldNamesMode::kIgnore, stringComparator); - return path() == realOther->path() && eltCmp.evaluate(_rhs == realOther->_rhs); + return path() == realOther->path() && eltCmp.evaluate(_rhsElem == realOther->_rhsElem); } - -Status ComparisonMatchExpression::init(StringData path, const BSONElement& rhs) { - _rhs = rhs; - - if (rhs.eoo()) { +Status ComparisonMatchExpression::_validate() { + if (!_rhsElem) { return Status(ErrorCodes::BadValue, "need a real operand"); } - if (rhs.type() == Undefined) { + if (_rhsElem.type() == BSONType::Undefined) { return Status(ErrorCodes::BadValue, "cannot compare to undefined"); } @@ -85,31 +82,59 @@ Status ComparisonMatchExpression::init(StringData path, const BSONElement& rhs) return Status(ErrorCodes::BadValue, "bad match type for ComparisonMatchExpression"); } + return Status::OK(); +} + +Status ComparisonMatchExpression::init(StringData path, + const boost::intrusive_ptr<Expression>& rhsExpr) { + auto exprConstant = dynamic_cast<ExpressionConstant*>(rhsExpr.get()); + if (exprConstant) { + BSONObjBuilder bob; + bob << path << exprConstant->getValue(); + _resolvedRhsExpr = bob.obj(); + _rhsElem = _resolvedRhsExpr.firstElement(); + } else { + return Status(ErrorCodes::BadValue, "$expr does not yet handle non-constant expressions"); + } + + auto status = _validate(); + if (!status.isOK()) { + return status; + } + return setPath(path); } +Status ComparisonMatchExpression::init(StringData path, const BSONElement& rhs) { + _rhsElem = rhs; + + auto status = _validate(); + if (!status.isOK()) { + return status; + } + + return setPath(path); +} bool ComparisonMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { - - if (e.canonicalType() != _rhs.canonicalType()) { + if (e.canonicalType() != _rhsElem.canonicalType()) { // some special cases // jstNULL and undefined are treated the same - if (e.canonicalType() + _rhs.canonicalType() == 5) { + if (e.canonicalType() + _rhsElem.canonicalType() == 5) { return matchType() == EQ || matchType() == LTE || matchType() == GTE; } - if (_rhs.type() == MaxKey || _rhs.type() == MinKey) { + if (_rhsElem.type() == MaxKey || _rhsElem.type() == MinKey) { return matchType() != EQ; } - return false; } // Special case handling for NaN. NaN is equal to NaN but // otherwise always compares to false. - if (std::isnan(e.numberDouble()) || std::isnan(_rhs.numberDouble())) { - bool bothNaN = std::isnan(e.numberDouble()) && std::isnan(_rhs.numberDouble()); + if (std::isnan(e.numberDouble()) || std::isnan(_rhsElem.numberDouble())) { + bool bothNaN = std::isnan(e.numberDouble()) && std::isnan(_rhsElem.numberDouble()); switch (matchType()) { case LT: return false; @@ -128,7 +153,7 @@ bool ComparisonMatchExpression::matchesSingleElement(const BSONElement& e, } } - int x = compareElementValues(e, _rhs, _collator); + int x = compareElementValues(e, _rhsElem, _collator); switch (matchType()) { case LT: @@ -170,7 +195,7 @@ void ComparisonMatchExpression::debugString(StringBuilder& debug, int level) con default: invariant(false); } - debug << " " << _rhs.toString(false); + debug << " " << _rhsElem.toString(false); MatchExpression::TagData* td = getTag(); if (NULL != td) { @@ -203,7 +228,7 @@ void ComparisonMatchExpression::serialize(BSONObjBuilder* out) const { invariant(false); } - out->append(path(), BSON(opString << _rhs)); + out->append(path(), BSON(opString << _rhsElem)); } // --------------- @@ -398,27 +423,27 @@ bool ExistsMatchExpression::equivalent(const MatchExpression* other) const { const std::string TypeMatchExpression::kMatchesAllNumbersAlias = "number"; const stdx::unordered_map<std::string, BSONType> TypeMatchExpression::typeAliasMap = { - {typeName(NumberDouble), NumberDouble}, - {typeName(String), String}, - {typeName(Object), Object}, - {typeName(Array), Array}, - {typeName(BinData), BinData}, - {typeName(Undefined), Undefined}, - {typeName(jstOID), jstOID}, - {typeName(Bool), Bool}, - {typeName(Date), Date}, - {typeName(jstNULL), jstNULL}, - {typeName(RegEx), RegEx}, - {typeName(DBRef), DBRef}, - {typeName(Code), Code}, - {typeName(Symbol), Symbol}, - {typeName(CodeWScope), CodeWScope}, - {typeName(NumberInt), NumberInt}, - {typeName(bsonTimestamp), bsonTimestamp}, - {typeName(NumberLong), NumberLong}, - {typeName(NumberDecimal), NumberDecimal}, - {typeName(MaxKey), MaxKey}, - {typeName(MinKey), MinKey}}; + {typeName(BSONType::NumberDouble), BSONType::NumberDouble}, + {typeName(BSONType::String), BSONType::String}, + {typeName(BSONType::Object), BSONType::Object}, + {typeName(BSONType::Array), BSONType::Array}, + {typeName(BSONType::BinData), BSONType::BinData}, + {typeName(BSONType::Undefined), BSONType::Undefined}, + {typeName(BSONType::jstOID), BSONType::jstOID}, + {typeName(BSONType::Bool), BSONType::Bool}, + {typeName(BSONType::Date), BSONType::Date}, + {typeName(BSONType::jstNULL), BSONType::jstNULL}, + {typeName(BSONType::RegEx), BSONType::RegEx}, + {typeName(BSONType::DBRef), BSONType::DBRef}, + {typeName(BSONType::Code), BSONType::Code}, + {typeName(BSONType::Symbol), BSONType::Symbol}, + {typeName(BSONType::CodeWScope), BSONType::CodeWScope}, + {typeName(BSONType::NumberInt), BSONType::NumberInt}, + {typeName(BSONType::bsonTimestamp), BSONType::bsonTimestamp}, + {typeName(BSONType::NumberLong), BSONType::NumberLong}, + {typeName(BSONType::NumberDecimal), BSONType::NumberDecimal}, + {typeName(BSONType::MaxKey), BSONType::MaxKey}, + {typeName(BSONType::MinKey), BSONType::MinKey}}; Status TypeMatchExpression::init(StringData path, Type type) { _type = std::move(type); diff --git a/src/mongo/db/matcher/expression_leaf.h b/src/mongo/db/matcher/expression_leaf.h index 984fc4653ca..49754b5c2bd 100644 --- a/src/mongo/db/matcher/expression_leaf.h +++ b/src/mongo/db/matcher/expression_leaf.h @@ -33,6 +33,7 @@ #include "mongo/bson/bsonobj.h" #include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression_path.h" +#include "mongo/db/pipeline/expression.h" #include "mongo/db/query/collation/collator_interface.h" #include "mongo/stdx/memory.h" #include "mongo/stdx/unordered_map.h" @@ -47,7 +48,7 @@ class CollatorInterface; class LeafMatchExpression : public PathMatchExpression { public: - LeafMatchExpression(MatchType matchType) : PathMatchExpression(matchType) {} + explicit LeafMatchExpression(MatchType matchType) : PathMatchExpression(matchType) {} virtual ~LeafMatchExpression() {} @@ -65,9 +66,10 @@ public: */ class ComparisonMatchExpression : public LeafMatchExpression { public: - ComparisonMatchExpression(MatchType type) : LeafMatchExpression(type) {} + explicit ComparisonMatchExpression(MatchType type) : LeafMatchExpression(type) {} Status init(StringData path, const BSONElement& rhs); + Status init(StringData path, const boost::intrusive_ptr<Expression>& rhsExpr); virtual ~ComparisonMatchExpression() {} @@ -87,7 +89,7 @@ public: virtual bool equivalent(const MatchExpression* other) const; const BSONElement& getData() const { - return _rhs; + return _rhsElem; } const CollatorInterface* getCollator() const { @@ -111,7 +113,11 @@ public: } protected: - BSONElement _rhs; + Status _validate(); + + BSONElement _rhsElem; + + BSONObj _resolvedRhsExpr; // Collator used to compare elements. By default, simple binary comparison will be used. const CollatorInterface* _collator = nullptr; @@ -122,7 +128,7 @@ public: EqualityMatchExpression() : ComparisonMatchExpression(EQ) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<EqualityMatchExpression>(); - e->init(path(), _rhs).transitional_ignore(); + invariantOK(e->init(path(), _rhsElem)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -136,7 +142,7 @@ public: LTEMatchExpression() : ComparisonMatchExpression(LTE) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<LTEMatchExpression>(); - e->init(path(), _rhs).transitional_ignore(); + invariantOK(e->init(path(), _rhsElem)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -150,7 +156,7 @@ public: LTMatchExpression() : ComparisonMatchExpression(LT) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<LTMatchExpression>(); - e->init(path(), _rhs).transitional_ignore(); + invariantOK(e->init(path(), _rhsElem)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -164,7 +170,7 @@ public: GTMatchExpression() : ComparisonMatchExpression(GT) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<GTMatchExpression>(); - e->init(path(), _rhs).transitional_ignore(); + invariantOK(e->init(path(), _rhsElem)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -178,7 +184,7 @@ public: GTEMatchExpression() : ComparisonMatchExpression(GTE) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<GTEMatchExpression>(); - e->init(path(), _rhs).transitional_ignore(); + invariantOK(e->init(path(), _rhsElem)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -204,7 +210,7 @@ public: virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<RegexMatchExpression> e = stdx::make_unique<RegexMatchExpression>(); - e->init(path(), _regex, _flags).transitional_ignore(); + invariantOK(e->init(path(), _regex, _flags)); if (getTag()) { e->setTag(getTag()->clone()); } @@ -244,7 +250,7 @@ public: virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ModMatchExpression> m = stdx::make_unique<ModMatchExpression>(); - m->init(path(), _divisor, _remainder).transitional_ignore(); + invariantOK(m->init(path(), _divisor, _remainder)); if (getTag()) { m->setTag(getTag()->clone()); } @@ -279,7 +285,7 @@ public: virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ExistsMatchExpression> e = stdx::make_unique<ExistsMatchExpression>(); - e->init(path()).transitional_ignore(); + invariantOK(e->init(path())); if (getTag()) { e->setTag(getTag()->clone()); } @@ -439,7 +445,7 @@ private: */ class BitTestMatchExpression : public LeafMatchExpression { public: - BitTestMatchExpression(MatchType type) : LeafMatchExpression(type) {} + explicit BitTestMatchExpression(MatchType type) : LeafMatchExpression(type) {} virtual ~BitTestMatchExpression() {} /** @@ -472,7 +478,7 @@ protected: * ownership. */ void initClone(BitTestMatchExpression* clone) const { - clone->init(path(), _bitPositions).transitional_ignore(); + invariantOK(clone->init(path(), _bitPositions)); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp index 3d1c87fbd26..af279e5d933 100644 --- a/src/mongo/db/matcher/expression_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_leaf_test.cpp @@ -35,6 +35,7 @@ #include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression_leaf.h" #include "mongo/db/matcher/expression_parser.h" +#include "mongo/db/pipeline/aggregation_context_fixture.h" #include "mongo/db/query/collation/collator_interface_mock.h" namespace mongo { @@ -96,10 +97,31 @@ TEST(EqOp, MatchesElement) { ASSERT(eq.equivalent(&eq)); } +TEST(EqOp, ConstantAggExprMatchesElement) { + BSONObj operand = BSON("a" << BSON("$expr" + << "$$userVar")); + BSONObj match = BSON("a" << 5); + BSONObj notMatch = BSON("a" << 6); + + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(5)); + auto expr = Expression::parseOperand( + expCtx, operand.firstElement()["$expr"], expCtx->variablesParseState); + expr = expr->optimize(); + + EqualityMatchExpression eq; + ASSERT_OK(eq.init("a", expr)); + ASSERT(eq.matchesSingleElement(match.firstElement())); + ASSERT_FALSE(eq.matchesSingleElement(notMatch.firstElement())); + + ASSERT(eq.equivalent(&eq)); +} + TEST(EqOp, InvalidEooOperand) { BSONObj operand; EqualityMatchExpression eq; - ASSERT(!eq.init("", operand.firstElement()).isOK()); + ASSERT_FALSE(eq.init("", operand.firstElement()).isOK()); } TEST(EqOp, MatchesScalar) { @@ -418,6 +440,27 @@ TEST(LtOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } +TEST(LtOp, ConstantAggExprMatchesElement) { + BSONObj operand = BSON("a" << BSON("$lt" << BSON("$expr" + << "$$userVar"))); + BSONObj match = BSON("a" << 5); + BSONObj notMatch = BSON("a" << 10); + + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(6)); + auto expr = Expression::parseOperand( + expCtx, operand.firstElement()["$lt"]["$expr"], expCtx->variablesParseState); + expr = expr->optimize(); + + LTMatchExpression lt; + ASSERT_OK(lt.init("a", expr)); + ASSERT(lt.matchesSingleElement(match.firstElement())); + ASSERT_FALSE(lt.matchesSingleElement(notMatch.firstElement())); + + ASSERT(lt.equivalent(<)); +} + /** TEST( LtOp, MatchesIndexKeyScalar ) { BSONObj operand = BSON( "$lt" << 6 ); @@ -483,6 +526,27 @@ TEST(LteOp, MatchesElement) { ASSERT(!lte.matchesSingleElement(notMatchWrongType.firstElement())); } +TEST(LteOp, ConstantAggExprMatchesElement) { + BSONObj operand = BSON("a" << BSON("$lte" << BSON("$expr" + << "$$userVar"))); + BSONObj match = BSON("a" << 5); + BSONObj notMatch = BSON("a" << 10); + + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(6)); + auto expr = Expression::parseOperand( + expCtx, operand.firstElement()["$lte"]["$expr"], expCtx->variablesParseState); + expr = expr->optimize(); + + LTEMatchExpression lte; + ASSERT_OK(lte.init("a", expr)); + ASSERT(lte.matchesSingleElement(match.firstElement())); + ASSERT_FALSE(lte.matchesSingleElement(notMatch.firstElement())); + + ASSERT(lte.equivalent(<e)); +} + TEST(LteOp, InvalidEooOperand) { BSONObj operand; LTEMatchExpression lte; @@ -737,6 +801,27 @@ TEST(GtOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } +TEST(GtOp, ConstantAggExprMatchesElement) { + BSONObj operand = BSON("a" << BSON("$gt" << BSON("$expr" + << "$$userVar"))); + BSONObj match = BSON("a" << 10); + BSONObj notMatch = BSON("a" << 0); + + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(5)); + auto expr = Expression::parseOperand( + expCtx, operand.firstElement()["$gt"]["$expr"], expCtx->variablesParseState); + expr = expr->optimize(); + + GTMatchExpression gt; + ASSERT_OK(gt.init("a", expr)); + ASSERT(gt.matchesSingleElement(match.firstElement())); + ASSERT_FALSE(gt.matchesSingleElement(notMatch.firstElement())); + + ASSERT(gt.equivalent(>)); +} + /** TEST( GtOp, MatchesIndexKeyScalar ) { BSONObj operand = BSON( "$gt" << 6 ); @@ -897,6 +982,27 @@ TEST(GteOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } +TEST(GteOp, ConstantAggExprMatchesElement) { + BSONObj operand = BSON("a" << BSON("$gte" << BSON("$expr" + << "$$userVar"))); + BSONObj match = BSON("a" << 10); + BSONObj notMatch = BSON("a" << 0); + + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(5)); + auto expr = Expression::parseOperand( + expCtx, operand.firstElement()["$gte"]["$expr"], expCtx->variablesParseState); + expr = expr->optimize(); + + GTEMatchExpression gte; + ASSERT_OK(gte.init("a", expr)); + ASSERT(gte.matchesSingleElement(match.firstElement())); + ASSERT_FALSE(gte.matchesSingleElement(notMatch.firstElement())); + + ASSERT(gte.equivalent(>e)); +} + TEST(RegexMatchExpression, MatchesElementExact) { BSONObj match = BSON("a" << "b"); diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp index 85c21e13bfc..1eff1a1138a 100644 --- a/src/mongo/db/matcher/expression_parser.cpp +++ b/src/mongo/db/matcher/expression_parser.cpp @@ -81,6 +81,8 @@ bool hasNode(const MatchExpression* root, MatchExpression::MatchType type) { namespace mongo { +constexpr StringData MatchExpressionParser::kAggExpression; + using std::string; using stdx::make_unique; @@ -91,7 +93,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison( const char* name, ComparisonMatchExpression* cmp, const BSONElement& e, - const CollatorInterface* collator) { + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { std::unique_ptr<ComparisonMatchExpression> temp(cmp); // Non-equality comparison match expressions cannot have @@ -102,25 +105,37 @@ StatusWithMatchExpression MatchExpressionParser::_parseComparison( return {Status(ErrorCodes::BadValue, ss)}; } - Status s = temp->init(name, e); - if (!s.isOK()) - return s; + if (_isAggExpression(e, expCtx)) { + auto expr = _parseAggExpression(e, expCtx); + auto s = temp->init(name, expr); + if (!s.isOK()) { + return s; + } + } else { + auto s = temp->init(name, e); + if (!s.isOK()) { + return s; + } + } + temp->setCollator(collator); return {std::move(temp)}; } -StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& context, - const AndMatchExpression* andSoFar, - const char* name, - const BSONElement& e, - const CollatorInterface* collator, - bool topLevel) { +StatusWithMatchExpression MatchExpressionParser::_parseSubField( + const BSONObj& context, + const AndMatchExpression* andSoFar, + const char* name, + const BSONElement& e, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + bool topLevel) { if (mongoutils::str::equals("$eq", e.fieldName())) - return _parseComparison(name, new EqualityMatchExpression(), e, collator); + return _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx); if (mongoutils::str::equals("$not", e.fieldName())) { - return _parseNot(name, e, collator, topLevel); + return _parseNot(name, e, collator, expCtx, topLevel); } auto parseExpMatchType = MatchExpressionParser::parsePathAcceptingKeyword(e); @@ -136,13 +151,13 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c switch (*parseExpMatchType) { case PathAcceptingKeyword::LESS_THAN: - return _parseComparison(name, new LTMatchExpression(), e, collator); + return _parseComparison(name, new LTMatchExpression(), e, collator, expCtx); case PathAcceptingKeyword::LESS_THAN_OR_EQUAL: - return _parseComparison(name, new LTEMatchExpression(), e, collator); + return _parseComparison(name, new LTEMatchExpression(), e, collator, expCtx); case PathAcceptingKeyword::GREATER_THAN: - return _parseComparison(name, new GTMatchExpression(), e, collator); + return _parseComparison(name, new GTMatchExpression(), e, collator, expCtx); case PathAcceptingKeyword::GREATER_THAN_OR_EQUAL: - return _parseComparison(name, new GTEMatchExpression(), e, collator); + return _parseComparison(name, new GTEMatchExpression(), e, collator, expCtx); case PathAcceptingKeyword::NOT_EQUAL: { if (RegEx == e.type()) { // Just because $ne can be rewritten as the negation of an @@ -150,7 +165,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c return {Status(ErrorCodes::BadValue, "Can't have regex as arg to $ne.")}; } StatusWithMatchExpression s = - _parseComparison(name, new EqualityMatchExpression(), e, collator); + _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx); if (!s.isOK()) return s; std::unique_ptr<NotMatchExpression> n = stdx::make_unique<NotMatchExpression>(); @@ -160,7 +175,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c return {std::move(n)}; } case PathAcceptingKeyword::EQUALITY: - return _parseComparison(name, new EqualityMatchExpression(), e, collator); + return _parseComparison(name, new EqualityMatchExpression(), e, collator, expCtx); case PathAcceptingKeyword::IN_EXPR: { if (e.type() != Array) @@ -169,7 +184,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c Status s = temp->init(name); if (!s.isOK()) return s; - s = _parseInExpression(temp.get(), e.Obj(), collator); + s = _parseInExpression(temp.get(), e.Obj(), collator, expCtx); if (!s.isOK()) return s; return {std::move(temp)}; @@ -182,7 +197,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c Status s = temp->init(name); if (!s.isOK()) return s; - s = _parseInExpression(temp.get(), e.Obj(), collator); + s = _parseInExpression(temp.get(), e.Obj(), collator, expCtx); if (!s.isOK()) return s; @@ -243,10 +258,10 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c } case PathAcceptingKeyword::TYPE: - return _parseType(name, e); + return _parseType(name, e, expCtx); case PathAcceptingKeyword::MOD: - return _parseMOD(name, e); + return _parseMOD(name, e, expCtx); case PathAcceptingKeyword::OPTIONS: { // TODO: try to optimize this @@ -264,14 +279,14 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c } case PathAcceptingKeyword::REGEX: { - return _parseRegexDocument(name, context); + return _parseRegexDocument(name, context, expCtx); } case PathAcceptingKeyword::ELEM_MATCH: - return _parseElemMatch(name, e, collator, topLevel); + return _parseElemMatch(name, e, collator, expCtx, topLevel); case PathAcceptingKeyword::ALL: - return _parseAll(name, e, collator, topLevel); + return _parseAll(name, e, collator, expCtx, topLevel); case PathAcceptingKeyword::WITHIN: case PathAcceptingKeyword::GEO_INTERSECTS: @@ -284,19 +299,19 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c // Handles bitwise query operators. case PathAcceptingKeyword::BITS_ALL_SET: { - return _parseBitTest<BitsAllSetMatchExpression>(name, e); + return _parseBitTest<BitsAllSetMatchExpression>(name, e, expCtx); } case PathAcceptingKeyword::BITS_ALL_CLEAR: { - return _parseBitTest<BitsAllClearMatchExpression>(name, e); + return _parseBitTest<BitsAllClearMatchExpression>(name, e, expCtx); } case PathAcceptingKeyword::BITS_ANY_SET: { - return _parseBitTest<BitsAnySetMatchExpression>(name, e); + return _parseBitTest<BitsAnySetMatchExpression>(name, e, expCtx); } case PathAcceptingKeyword::BITS_ANY_CLEAR: { - return _parseBitTest<BitsAnyClearMatchExpression>(name, e); + return _parseBitTest<BitsAnyClearMatchExpression>(name, e, expCtx); } case PathAcceptingKeyword::INTERNAL_SCHEMA_FMOD: @@ -318,7 +333,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c str::stream() << "$_internalSchemaObjectMatch must be an object"); } - auto parsedSubObjExpr = _parse(e.Obj(), collator, topLevel); + auto parsedSubObjExpr = _parse(e.Obj(), collator, expCtx, topLevel); if (!parsedSubObjExpr.isOK()) { return parsedSubObjExpr; } @@ -363,9 +378,11 @@ StatusWithMatchExpression MatchExpressionParser::_parseSubField(const BSONObj& c mongoutils::str::stream() << "not handled: " << e.fieldName())}; } -StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, - const CollatorInterface* collator, - bool topLevel) { +StatusWithMatchExpression MatchExpressionParser::_parse( + const BSONObj& obj, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + bool topLevel) { std::unique_ptr<AndMatchExpression> root = stdx::make_unique<AndMatchExpression>(); const bool childIsTopLevel = false; @@ -380,7 +397,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, if (e.type() != Array) return {Status(ErrorCodes::BadValue, "$or must be an array")}; std::unique_ptr<OrMatchExpression> temp = stdx::make_unique<OrMatchExpression>(); - Status s = _parseTreeList(e.Obj(), temp.get(), collator, childIsTopLevel); + Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel); if (!s.isOK()) return s; root->add(temp.release()); @@ -388,7 +405,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, if (e.type() != Array) return {Status(ErrorCodes::BadValue, "$and must be an array")}; std::unique_ptr<AndMatchExpression> temp = stdx::make_unique<AndMatchExpression>(); - Status s = _parseTreeList(e.Obj(), temp.get(), collator, childIsTopLevel); + Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel); if (!s.isOK()) return s; root->add(temp.release()); @@ -396,7 +413,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, if (e.type() != Array) return {Status(ErrorCodes::BadValue, "$nor must be an array")}; std::unique_ptr<NorMatchExpression> temp = stdx::make_unique<NorMatchExpression>(); - Status s = _parseTreeList(e.Obj(), temp.get(), collator, childIsTopLevel); + Status s = _parseTreeList(e.Obj(), temp.get(), collator, expCtx, childIsTopLevel); if (!s.isOK()) return s; root->add(temp.release()); @@ -434,7 +451,7 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, } else if (mongoutils::str::equals("_internalSchemaCond", rest)) { auto condExpr = _parseInternalSchemaFixedArityArgument<InternalSchemaCondMatchExpression>( - InternalSchemaCondMatchExpression::kName, e, collator); + InternalSchemaCondMatchExpression::kName, e, collator, expCtx); if (!condExpr.isOK()) { return condExpr.getStatus(); } @@ -445,7 +462,8 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, return { Status(ErrorCodes::TypeMismatch, "$_internalSchemaXor must be an array")}; auto xorExpr = stdx::make_unique<InternalSchemaXorMatchExpression>(); - Status s = _parseTreeList(e.Obj(), xorExpr.get(), collator, childIsTopLevel); + Status s = + _parseTreeList(e.Obj(), xorExpr.get(), collator, expCtx, childIsTopLevel); if (!s.isOK()) return s; root->add(xorExpr.release()); @@ -493,29 +511,28 @@ StatusWithMatchExpression MatchExpressionParser::_parse(const BSONObj& obj, continue; } - if (_isExpressionDocument(e, false)) { - Status s = _parseSub(e.fieldName(), e.Obj(), root.get(), collator, childIsTopLevel); + if (_isExpressionDocument(e, false, expCtx)) { + Status s = + _parseSub(e.fieldName(), e.Obj(), root.get(), collator, expCtx, childIsTopLevel); if (!s.isOK()) return s; continue; } if (e.type() == RegEx) { - StatusWithMatchExpression result = _parseRegexElement(e.fieldName(), e); + StatusWithMatchExpression result = _parseRegexElement(e.fieldName(), e, expCtx); if (!result.isOK()) return result; root->add(result.getValue().release()); continue; } - std::unique_ptr<ComparisonMatchExpression> eq = - stdx::make_unique<EqualityMatchExpression>(); - Status s = eq->init(e.fieldName(), e); - if (!s.isOK()) - return s; - eq->setCollator(collator); + auto eq = + _parseComparison(e.fieldName(), new EqualityMatchExpression(), e, collator, expCtx); + if (!eq.isOK()) + return eq; - root->add(eq.release()); + root->add(eq.getValue().release()); } if (root->numChildren() == 1) { @@ -531,6 +548,7 @@ Status MatchExpressionParser::_parseSub(const char* name, const BSONObj& sub, AndMatchExpression* root, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel) { // The one exception to {field : {fully contained argument} } is, of course, geo. Example: // sub == { field : {$near[Sphere]: [0,0], $maxDistance: 1000, $minDistance: 10 } } @@ -572,7 +590,7 @@ Status MatchExpressionParser::_parseSub(const char* name, const bool childIsTopLevel = false; StatusWithMatchExpression s = - _parseSubField(sub, root, name, deep, collator, childIsTopLevel); + _parseSubField(sub, root, name, deep, collator, expCtx, childIsTopLevel); if (!s.isOK()) return s.getStatus(); @@ -583,7 +601,10 @@ Status MatchExpressionParser::_parseSub(const char* name, return Status::OK(); } -bool MatchExpressionParser::_isExpressionDocument(const BSONElement& e, bool allowIncompleteDBRef) { +bool MatchExpressionParser::_isExpressionDocument( + const BSONElement& e, + bool allowIncompleteDBRef, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { if (e.type() != Object) return false; @@ -599,6 +620,10 @@ bool MatchExpressionParser::_isExpressionDocument(const BSONElement& e, bool all return false; } + if (_isAggExpression(e, expCtx)) { + return false; + } + return true; } @@ -643,7 +668,8 @@ bool MatchExpressionParser::_isDBRefDocument(const BSONObj& obj, bool allowIncom return hasRef && hasID; } -StatusWithMatchExpression MatchExpressionParser::_parseMOD(const char* name, const BSONElement& e) { +StatusWithMatchExpression MatchExpressionParser::_parseMOD( + const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx) { if (e.type() != Array) return {Status(ErrorCodes::BadValue, "malformed mod, needs to be an array")}; @@ -671,8 +697,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseMOD(const char* name, con return {std::move(temp)}; } -StatusWithMatchExpression MatchExpressionParser::_parseRegexElement(const char* name, - const BSONElement& e) { +StatusWithMatchExpression MatchExpressionParser::_parseRegexElement( + const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx) { if (e.type() != RegEx) return {Status(ErrorCodes::BadValue, "not a regex")}; @@ -683,8 +709,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseRegexElement(const char* return {std::move(temp)}; } -StatusWithMatchExpression MatchExpressionParser::_parseRegexDocument(const char* name, - const BSONObj& doc) { +StatusWithMatchExpression MatchExpressionParser::_parseRegexDocument( + const char* name, const BSONObj& doc, const boost::intrusive_ptr<ExpressionContext>& expCtx) { string regex; string regexOptions; @@ -725,9 +751,11 @@ StatusWithMatchExpression MatchExpressionParser::_parseRegexDocument(const char* return {std::move(temp)}; } -Status MatchExpressionParser::_parseInExpression(InMatchExpression* inExpression, - const BSONObj& theArray, - const CollatorInterface* collator) { +Status MatchExpressionParser::_parseInExpression( + InMatchExpression* inExpression, + const BSONObj& theArray, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { inExpression->setCollator(collator); std::vector<BSONElement> equalities; BSONObjIterator i(theArray); @@ -735,7 +763,7 @@ Status MatchExpressionParser::_parseInExpression(InMatchExpression* inExpression BSONElement e = i.next(); // Allow DBRefs, but reject all fields with names starting with $. - if (_isExpressionDocument(e, false)) { + if (_isExpressionDocument(e, false, expCtx)) { return Status(ErrorCodes::BadValue, "cannot nest $ under $in"); } @@ -748,6 +776,10 @@ Status MatchExpressionParser::_parseInExpression(InMatchExpression* inExpression if (!s.isOK()) return s; } else { + if (_isAggExpression(e, expCtx)) { + return Status(ErrorCodes::BadValue, "$expr not supported for $in"); + } + equalities.push_back(e); } } @@ -783,8 +815,10 @@ StatusWith<std::unique_ptr<TypeMatchExpression>> MatchExpressionParser::parseTyp return {std::move(typeExpr)}; } -StatusWithMatchExpression MatchExpressionParser::_parseType(const char* name, - const BSONElement& elt) { +StatusWithMatchExpression MatchExpressionParser::_parseType( + const char* name, + const BSONElement& elt, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { if (!elt.isNumber() && elt.type() != BSONType::String) { return Status(ErrorCodes::TypeMismatch, "argument to $type is not a number or a string"); } @@ -818,10 +852,12 @@ StatusWithMatchExpression MatchExpressionParser::_parseType(const char* name, return {std::move(typeExpr)}; } -StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(const char* name, - const BSONElement& e, - const CollatorInterface* collator, - bool topLevel) { +StatusWithMatchExpression MatchExpressionParser::_parseElemMatch( + const char* name, + const BSONElement& e, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + bool topLevel) { if (e.type() != Object) return {Status(ErrorCodes::BadValue, "$elemMatch needs an Object")}; @@ -836,7 +872,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(const char* nam // 3) expression is not a WHERE operator. WHERE works on objects instead // of specific field. bool isElemMatchValue = false; - if (_isExpressionDocument(e, true)) { + if (_isExpressionDocument(e, true, expCtx)) { BSONObj o = e.Obj(); BSONElement elt = o.firstElement(); invariant(!elt.eoo()); @@ -854,7 +890,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(const char* nam // value case AndMatchExpression theAnd; - Status s = _parseSub("", obj, &theAnd, collator, topLevel); + Status s = _parseSub("", obj, &theAnd, collator, expCtx, topLevel); if (!s.isOK()) return s; @@ -878,7 +914,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(const char* nam // object case - StatusWithMatchExpression subRaw = _parse(obj, collator, topLevel); + StatusWithMatchExpression subRaw = _parse(obj, collator, expCtx, topLevel); if (!subRaw.isOK()) return subRaw; std::unique_ptr<MatchExpression> sub = std::move(subRaw.getValue()); @@ -898,10 +934,12 @@ StatusWithMatchExpression MatchExpressionParser::_parseElemMatch(const char* nam return {std::move(temp)}; } -StatusWithMatchExpression MatchExpressionParser::_parseAll(const char* name, - const BSONElement& e, - const CollatorInterface* collator, - bool topLevel) { +StatusWithMatchExpression MatchExpressionParser::_parseAll( + const char* name, + const BSONElement& e, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + bool topLevel) { if (e.type() != Array) return {Status(ErrorCodes::BadValue, "$all needs an array")}; @@ -931,7 +969,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(const char* name, const bool childIsTopLevel = false; StatusWithMatchExpression inner = _parseElemMatch( - name, hopefullyElemMatchObj.firstElement(), collator, childIsTopLevel); + name, hopefullyElemMatchObj.firstElement(), collator, expCtx, childIsTopLevel); if (!inner.isOK()) return inner; myAnd->add(inner.getValue().release()); @@ -971,8 +1009,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseAll(const char* name, } template <class T> -StatusWithMatchExpression MatchExpressionParser::_parseBitTest(const char* name, - const BSONElement& e) { +StatusWithMatchExpression MatchExpressionParser::_parseBitTest( + const char* name, const BSONElement& e, const boost::intrusive_ptr<ExpressionContext>& expCtx) { std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression = stdx::make_unique<T>(); if (e.type() == BSONType::Array) { @@ -1179,7 +1217,10 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFmod(const template <class T> StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityArgument( - StringData name, const BSONElement& input, const CollatorInterface* collator) { + StringData name, + const BSONElement& input, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { constexpr auto arity = T::arity(); if (input.type() != BSONType::Array) { return {ErrorCodes::FailedToParse, @@ -1208,7 +1249,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseInternalSchemaFixedArityA } const bool isTopLevel = false; - auto subexpr = _parse(elem.embeddedObject(), collator, isTopLevel); + auto subexpr = _parse(elem.embeddedObject(), collator, expCtx, isTopLevel); if (!subexpr.isOK()) { return subexpr.getStatus(); } @@ -1355,6 +1396,33 @@ StatusWithMatchExpression MatchExpressionParser::_parseGeo(const char* name, } } +bool MatchExpressionParser::_isAggExpression( + BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) { + if (!expCtx) { + return false; + } + + if (BSONType::Object != elem.type()) { + return false; + } + + auto obj = elem.embeddedObject(); + if (obj.nFields() != 1) { + return false; + } + + return obj.firstElementFieldName() == kAggExpression; +} + +boost::intrusive_ptr<Expression> MatchExpressionParser::_parseAggExpression( + BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) { + invariant(expCtx); + + auto expr = Expression::parseOperand( + expCtx, elem.embeddedObject().firstElement(), expCtx->variablesParseState); + return expr->optimize(); +} + namespace { // Maps from query operator string name to operator PathAcceptingKeyword. std::unique_ptr<StringMap<PathAcceptingKeyword>> queryOperatorMap; diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h index a39410a99b0..88ac25551a9 100644 --- a/src/mongo/db/matcher/expression_parser.h +++ b/src/mongo/db/matcher/expression_parser.h @@ -36,6 +36,7 @@ #include "mongo/db/matcher/expression_leaf.h" #include "mongo/db/matcher/expression_tree.h" #include "mongo/db/matcher/extensions_callback.h" +#include "mongo/db/pipeline/expression_context.h" #include "mongo/stdx/functional.h" namespace mongo { @@ -84,6 +85,8 @@ public: */ static const double kLongLongMaxPlusOneAsDouble; + static constexpr StringData kAggExpression = "$expr"_sd; + /** * Parses PathAcceptingKeyword from 'typeElem'. Returns 'defaultKeyword' if 'typeElem' * doesn't represent a known type, or represents PathAcceptingKeyword::EQUALITY which is not @@ -96,11 +99,14 @@ public: * caller has to maintain ownership obj * the tree has views (BSONElement) into obj */ - static StatusWithMatchExpression parse(const BSONObj& obj, - const ExtensionsCallback& extensionsCallback, - const CollatorInterface* collator) { + static StatusWithMatchExpression parse( + const BSONObj& obj, + const ExtensionsCallback& extensionsCallback, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr) { const bool topLevelCall = true; - return MatchExpressionParser(&extensionsCallback)._parse(obj, collator, topLevelCall); + return MatchExpressionParser(&extensionsCallback) + ._parse(obj, collator, expCtx, topLevelCall); } /** @@ -145,7 +151,9 @@ private: * { $id : "x" } = false (if incomplete DBRef is allowed) * { $db : "mydb" } = false (if incomplete DBRef is allowed) */ - bool _isExpressionDocument(const BSONElement& e, bool allowIncompleteDBRef); + bool _isExpressionDocument(const BSONElement& e, + bool allowIncompleteDBRef, + const boost::intrusive_ptr<ExpressionContext>& expCtx); /** * { $ref: "s", $id: "x" } = true @@ -166,6 +174,7 @@ private: */ StatusWithMatchExpression _parse(const BSONObj& obj, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); /** @@ -177,6 +186,7 @@ private: const BSONObj& obj, AndMatchExpression* root, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); /** @@ -189,24 +199,38 @@ private: const char* name, const BSONElement& e, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); - StatusWithMatchExpression _parseComparison(const char* name, - ComparisonMatchExpression* cmp, - const BSONElement& e, - const CollatorInterface* collator); + StatusWithMatchExpression _parseComparison( + const char* name, + ComparisonMatchExpression* cmp, + const BSONElement& e, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx); - StatusWithMatchExpression _parseMOD(const char* name, const BSONElement& e); + StatusWithMatchExpression _parseMOD(const char* name, + const BSONElement& e, + const boost::intrusive_ptr<ExpressionContext>& expCtx); - StatusWithMatchExpression _parseRegexElement(const char* name, const BSONElement& e); + StatusWithMatchExpression _parseRegexElement( + const char* name, + const BSONElement& e, + const boost::intrusive_ptr<ExpressionContext>& expCtx); - StatusWithMatchExpression _parseRegexDocument(const char* name, const BSONObj& doc); + StatusWithMatchExpression _parseRegexDocument( + const char* name, + const BSONObj& doc, + const boost::intrusive_ptr<ExpressionContext>& expCtx); Status _parseInExpression(InMatchExpression* entries, const BSONObj& theArray, - const CollatorInterface* collator); + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx); - StatusWithMatchExpression _parseType(const char* name, const BSONElement& elt); + StatusWithMatchExpression _parseType(const char* name, + const BSONElement& elt, + const boost::intrusive_ptr<ExpressionContext>& expCtx); StatusWithMatchExpression _parseGeo(const char* name, PathAcceptingKeyword type, @@ -217,11 +241,13 @@ private: StatusWithMatchExpression _parseElemMatch(const char* name, const BSONElement& e, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); StatusWithMatchExpression _parseAll(const char* name, const BSONElement& e, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); // tree @@ -229,18 +255,22 @@ private: Status _parseTreeList(const BSONObj& arr, ListOfMatchExpression* out, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); StatusWithMatchExpression _parseNot(const char* name, const BSONElement& e, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel); /** * Parses 'e' into a BitTestMatchExpression. */ template <class T> - StatusWithMatchExpression _parseBitTest(const char* name, const BSONElement& e); + StatusWithMatchExpression _parseBitTest(const char* name, + const BSONElement& e, + const boost::intrusive_ptr<ExpressionContext>& expCtx); /** * Converts 'theArray', a BSONArray of integers, into a std::vector of integers. @@ -254,7 +284,10 @@ private: */ template <class T> StatusWithMatchExpression _parseInternalSchemaFixedArityArgument( - StringData name, const BSONElement& elem, const CollatorInterface* collator); + StringData name, + const BSONElement& elem, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx); /** * Parses the given BSONElement into a single integer argument and creates a MatchExpression @@ -278,6 +311,11 @@ private: StatusWithMatchExpression _parseInternalSchemaMatchArrayIndex( const char* path, const BSONElement& elem, const CollatorInterface* collator); + bool _isAggExpression(BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx); + + boost::intrusive_ptr<Expression> _parseAggExpression( + BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx); + // Performs parsing for the match extensions. We do not own this pointer - it has to live // as long as the parser is active. const ExtensionsCallback* _extensionsCallback; diff --git a/src/mongo/db/matcher/expression_parser_geo_test.cpp b/src/mongo/db/matcher/expression_parser_geo_test.cpp index 63008393ad6..4e4197a422d 100644 --- a/src/mongo/db/matcher/expression_parser_geo_test.cpp +++ b/src/mongo/db/matcher/expression_parser_geo_test.cpp @@ -35,6 +35,7 @@ #include "mongo/db/matcher/expression.h" #include "mongo/db/matcher/expression_geo.h" #include "mongo/db/matcher/extensions_callback_disallow_extensions.h" +#include "mongo/db/pipeline/aggregation_context_fixture.h" namespace mongo { @@ -53,6 +54,19 @@ TEST(MatchExpressionParserGeo, WithinBox) { ASSERT(result.getValue()->matchesBSON(fromjson("{a: {x: 5, y:5.1}}"))); } +TEST(MatchExpressionParserGeo, RejectsExprAsGeometry) { + const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(fromjson("{type: 'Point', coordinates:[0,0]}}"))); + + BSONObj query = fromjson("{a:{$geoIntersects:{$geometry: {$expr: '$$userVar'} }}}"); + + const CollatorInterface* collator = nullptr; + StatusWithMatchExpression result = + MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); + ASSERT_NOT_OK(result.getStatus()); +} + TEST(MatchExpressionParserGeoNear, ParseNear) { BSONObj query = fromjson( "{loc:{$near:{$maxDistance:100, " diff --git a/src/mongo/db/matcher/expression_parser_leaf_test.cpp b/src/mongo/db/matcher/expression_parser_leaf_test.cpp index c9bae20aac7..90b4c80dfc4 100644 --- a/src/mongo/db/matcher/expression_parser_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_parser_leaf_test.cpp @@ -34,6 +34,7 @@ #include "mongo/db/matcher/expression_leaf.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/matcher/extensions_callback_disallow_extensions.h" +#include "mongo/db/pipeline/expression_context_for_test.h" #include "mongo/db/query/collation/collator_interface_mock.h" #include "mongo/platform/decimal128.h" #include "mongo/unittest/unittest.h" @@ -49,7 +50,7 @@ TEST(MatchExpressionParserLeafTest, NullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -62,18 +63,69 @@ TEST(MatchExpressionParserLeafTest, Collation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, ConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$expr" + << "$$userVar")); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj match = BSON("x" << 123); + BSONObj notMatch = BSON("x" << 321); + + ASSERT_TRUE(expr->matchesBSON(match)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + +TEST(MatchExpressionParserLeafTest, ConstantExprFailsWithMissingVariable) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$expr" + << "$$userVar")); + + ASSERT_THROWS_CODE(auto sw = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx), + UserException, + 17276); +} + +TEST(MatchExpressionParserLeafTest, ConstantExprFailsWithMissingExpressionContext) { + boost::intrusive_ptr<ExpressionContextForTest> nullExpCtx; + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$expr" + << "$$userVar")); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, nullExpCtx); + + ASSERT_NOT_OK(result.getStatus()); +} + TEST(MatchExpressionParserLeafTest, SimpleEQ2) { BSONObj query = BSON("x" << BSON("$eq" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 2))); @@ -85,7 +137,7 @@ TEST(MatchExpressionParserLeafTest, SimpleEQUndefined) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, EQNullCollation) { @@ -94,7 +146,7 @@ TEST(MatchExpressionParserLeafTest, EQNullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -107,18 +159,43 @@ TEST(MatchExpressionParserLeafTest, EQCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, EQConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$eq" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj match = BSON("x" << 123); + BSONObj notMatch = BSON("x" << 321); + + ASSERT_TRUE(expr->matchesBSON(match)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleGT1) { BSONObj query = BSON("x" << BSON("$gt" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 3))); @@ -130,7 +207,7 @@ TEST(MatchExpressionParserLeafTest, GTNullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType()); GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -143,18 +220,43 @@ TEST(MatchExpressionParserLeafTest, GTCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType()); GTMatchExpression* match = static_cast<GTMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, GTConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$gt" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj match = BSON("x" << 500); + BSONObj notMatch = BSON("x" << 0); + + ASSERT_TRUE(expr->matchesBSON(match)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleLT1) { BSONObj query = BSON("x" << BSON("$lt" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2))); @@ -167,7 +269,7 @@ TEST(MatchExpressionParserLeafTest, LTNullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType()); LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -180,18 +282,43 @@ TEST(MatchExpressionParserLeafTest, LTCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType()); LTMatchExpression* match = static_cast<LTMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, LTConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$lt" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj match = BSON("x" << 0); + BSONObj notMatch = BSON("x" << 500); + + ASSERT_TRUE(expr->matchesBSON(match)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleGTE1) { BSONObj query = BSON("x" << BSON("$gte" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 2))); @@ -204,7 +331,7 @@ TEST(MatchExpressionParserLeafTest, GTENullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType()); GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -217,18 +344,45 @@ TEST(MatchExpressionParserLeafTest, GTECollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType()); GTEMatchExpression* match = static_cast<GTEMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, GTEConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$gte" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj matchEq = BSON("x" << 123); + BSONObj matchGt = BSON("x" << 500); + BSONObj notMatch = BSON("x" << 0); + + ASSERT_TRUE(expr->matchesBSON(matchEq)); + ASSERT_TRUE(expr->matchesBSON(matchGt)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleLTE1) { BSONObj query = BSON("x" << BSON("$lte" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 2))); @@ -241,7 +395,7 @@ TEST(MatchExpressionParserLeafTest, LTENullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType()); LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -254,18 +408,45 @@ TEST(MatchExpressionParserLeafTest, LTECollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType()); LTEMatchExpression* match = static_cast<LTEMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, LTEConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$lte" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj matchEq = BSON("x" << 123); + BSONObj matchLt = BSON("x" << 0); + BSONObj notMatch = BSON("x" << 500); + + ASSERT_TRUE(expr->matchesBSON(matchEq)); + ASSERT_TRUE(expr->matchesBSON(matchLt)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleNE1) { BSONObj query = BSON("x" << BSON("$ne" << 2)); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2))); @@ -278,7 +459,7 @@ TEST(MatchExpressionParserLeafTest, NENullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType()); MatchExpression* child = result.getValue()->getChild(0); ASSERT_EQUALS(MatchExpression::EQ, child->matchType()); @@ -293,7 +474,7 @@ TEST(MatchExpressionParserLeafTest, NECollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType()); MatchExpression* child = result.getValue()->getChild(0); ASSERT_EQUALS(MatchExpression::EQ, child->matchType()); @@ -301,32 +482,57 @@ TEST(MatchExpressionParserLeafTest, NECollation) { ASSERT_TRUE(eqMatch->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, NEConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$ne" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + + ASSERT_OK(result.getStatus()); + ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType()); + + auto expr = result.getValue().get(); + + BSONObj match = BSON("x" << 0); + BSONObj notMatch = BSON("x" << 123); + + ASSERT_TRUE(expr->matchesBSON(match)); + ASSERT_FALSE(expr->matchesBSON(notMatch)); +} + TEST(MatchExpressionParserLeafTest, SimpleModBad1) { BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2))); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); query = BSON("x" << BSON("$mod" << BSON_ARRAY(3))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(!result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2 << 4))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(!result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$mod" << BSON_ARRAY("q" << 2))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(!result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$mod" << 3)); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(!result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$mod" << BSON("a" << 1 << "b" << 2))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(!result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, SimpleMod1) { @@ -334,7 +540,7 @@ TEST(MatchExpressionParserLeafTest, SimpleMod1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 5))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 4))); @@ -346,7 +552,7 @@ TEST(MatchExpressionParserLeafTest, SimpleModNotNumber) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 2))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 4))); @@ -355,13 +561,29 @@ TEST(MatchExpressionParserLeafTest, SimpleModNotNumber) { << "a"))); } +TEST(MatchExpressionParserLeafTest, ModConstantExprFails) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$mod" << BSON("$expr" + << "$$userVar"))); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(BSON_ARRAY(10 << 2))); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue); +} + TEST(MatchExpressionParserLeafTest, IdCollation) { BSONObj query = BSON("$id" << "string"); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -373,42 +595,93 @@ TEST(MatchExpressionParserLeafTest, IdNullCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, IdConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("$id" << BSON("$expr" + << "$$userVar")); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + ASSERT_OK(result.getStatus()); + + ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); +} + TEST(MatchExpressionParserLeafTest, RefCollation) { BSONObj query = BSON("$ref" << "coll"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == nullptr); } +TEST(MatchExpressionParserLeafTest, RefConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("$ref" << BSON("$expr" + << "$$userVar")); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(std::string("colName"))); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + ASSERT_OK(result.getStatus()); + + ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); +} + TEST(MatchExpressionParserLeafTest, DbCollation) { BSONObj query = BSON("$db" << "db"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); EqualityMatchExpression* match = static_cast<EqualityMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == nullptr); } +TEST(MatchExpressionParserLeafTest, DbConstantExpr) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("$db" << BSON("$expr" + << "$$userVar")); + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(std::string("dbName"))); + + auto result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), collator, expCtx); + ASSERT_OK(result.getStatus()); + + ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType()); +} + TEST(MatchExpressionParserLeafTest, SimpleIN1) { BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(2 << 3))); const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(result.getValue()->matchesBSON(BSON("x" << 2))); @@ -420,7 +693,7 @@ TEST(MatchExpressionParserLeafTest, INNullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType()); InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == collator); @@ -431,12 +704,39 @@ TEST(MatchExpressionParserLeafTest, INCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType()); InMatchExpression* match = static_cast<InMatchExpression*>(result.getValue().get()); ASSERT_TRUE(match->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, INConstantExprFails) { + CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + + // $expr represents entire $in array. + BSONObj query = BSON("x" << BSON("$in" << BSON("$expr" + << "userVar"))); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 2))); + + StatusWithMatchExpression result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx); + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue); + + // $expr represents a single element of the $in array. + query = BSON("x" << BSON("$in" << BSON_ARRAY(1 << BSON("$expr" + << "userVar")))); + varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx); + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue); +} + TEST(MatchExpressionParserLeafTest, INSingleDBRef) { OID oid = OID::gen(); BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref" @@ -448,7 +748,7 @@ TEST(MatchExpressionParserLeafTest, INSingleDBRef) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); OID oidx = OID::gen(); ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref" @@ -531,7 +831,7 @@ TEST(MatchExpressionParserLeafTest, INMultipleDBRef) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); OID oidx = OID::gen(); ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref" @@ -673,7 +973,7 @@ TEST(MatchExpressionParserLeafTest, INDBRefWithOptionalField1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); OID oidx = OID::gen(); ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref" @@ -717,14 +1017,14 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) { << "$foo" << 1)))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); OID oid = OID::gen(); // missing $ref field query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$id" << oid << "foo" << 3)))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); // missing $id and $ref field query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$db" @@ -732,7 +1032,7 @@ TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) { << "foo" << 3)))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INExpressionDocument) { @@ -740,7 +1040,7 @@ TEST(MatchExpressionParserLeafTest, INExpressionDocument) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INNotArray) { @@ -748,7 +1048,7 @@ TEST(MatchExpressionParserLeafTest, INNotArray) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INUndefined) { @@ -756,7 +1056,7 @@ TEST(MatchExpressionParserLeafTest, INUndefined) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INNotElemMatch) { @@ -764,7 +1064,7 @@ TEST(MatchExpressionParserLeafTest, INNotElemMatch) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INRegexTooLong) { @@ -777,7 +1077,7 @@ TEST(MatchExpressionParserLeafTest, INRegexTooLong) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INRegexTooLong2) { @@ -786,7 +1086,7 @@ TEST(MatchExpressionParserLeafTest, INRegexTooLong2) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, INRegexStuff) { @@ -801,7 +1101,7 @@ TEST(MatchExpressionParserLeafTest, INRegexStuff) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); BSONObj matchFirst = BSON("a" << "ax"); @@ -828,7 +1128,7 @@ TEST(MatchExpressionParserLeafTest, SimpleNIN1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 1))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2))); @@ -840,7 +1140,7 @@ TEST(MatchExpressionParserLeafTest, NINNotArray) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, NINNullCollation) { @@ -848,7 +1148,7 @@ TEST(MatchExpressionParserLeafTest, NINNullCollation) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType()); MatchExpression* child = result.getValue()->getChild(0); ASSERT_EQUALS(MatchExpression::MATCH_IN, child->matchType()); @@ -861,7 +1161,7 @@ TEST(MatchExpressionParserLeafTest, NINCollation) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType()); MatchExpression* child = result.getValue()->getChild(0); ASSERT_EQUALS(MatchExpression::MATCH_IN, child->matchType()); @@ -869,6 +1169,33 @@ TEST(MatchExpressionParserLeafTest, NINCollation) { ASSERT_TRUE(inMatch->getCollator() == &collator); } +TEST(MatchExpressionParserLeafTest, NINConstantExprFails) { + CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + + // $expr represents entire $in array. + BSONObj query = BSON("x" << BSON("$nin" << BSON("$expr" + << "userVar"))); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 2))); + + StatusWithMatchExpression result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx); + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue); + + // $expr represents a single element of the $in array. + query = BSON("x" << BSON("$nin" << BSON_ARRAY(1 << BSON("$expr" + << "userVar")))); + varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + result = MatchExpressionParser::parse( + query, ExtensionsCallbackDisallowExtensions(), &collator, expCtx); + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(result.getStatus().code(), ErrorCodes::BadValue); +} + TEST(MatchExpressionParserLeafTest, Regex1) { BSONObjBuilder b; b.appendRegex("x", "abc", "i"); @@ -876,7 +1203,7 @@ TEST(MatchExpressionParserLeafTest, Regex1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -894,7 +1221,7 @@ TEST(MatchExpressionParserLeafTest, Regex2) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -912,7 +1239,7 @@ TEST(MatchExpressionParserLeafTest, Regex3) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -931,26 +1258,26 @@ TEST(MatchExpressionParserLeafTest, RegexBad) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); // $regex does not with numbers query = BSON("x" << BSON("$regex" << 123)); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$regex" << BSON_ARRAY("abc"))); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$optionas" << "i")); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); query = BSON("x" << BSON("$options" << "i")); result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) { @@ -959,7 +1286,7 @@ TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); const auto value = "a\0b"_sd; ASSERT(result.getValue()->matchesBSON(BSON("x" << value))); @@ -967,6 +1294,34 @@ TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) { << "a"))); } +TEST(MatchExpressionParserLeafTest, RegexWithConstantExprFails) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$options" << BSON("$expr" + << "userVar") + << "$regex" + << "abc")); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(std::string("i"))); + + StatusWithMatchExpression result = + MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); + ASSERT_NOT_OK(result.getStatus()); + + + query = BSON("x" << BSON("$options" + << "i" + << "$regex" + << BSON("$expr" + << "userVar"))); + varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(std::string("abc"))); + + result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); + ASSERT_NOT_OK(result.getStatus()); +} + TEST(MatchExpressionParserLeafTest, ExistsYes1) { BSONObjBuilder b; b.appendBool("$exists", true); @@ -974,7 +1329,7 @@ TEST(MatchExpressionParserLeafTest, ExistsYes1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -989,7 +1344,7 @@ TEST(MatchExpressionParserLeafTest, ExistsNO1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -1002,7 +1357,7 @@ TEST(MatchExpressionParserLeafTest, Type1) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << "abc"))); @@ -1014,7 +1369,7 @@ TEST(MatchExpressionParserLeafTest, Type2) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(result.getValue()->matchesBSON(BSON("x" << 5.3))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5))); @@ -1025,7 +1380,7 @@ TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3))); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5))); @@ -1036,7 +1391,7 @@ TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT_FALSE(result.getValue()->matchesBSON(BSON("x" << 5.3))); ASSERT_TRUE(result.getValue()->matchesBSON(BSON("x" << mongo::Decimal128("1")))); @@ -1047,7 +1402,7 @@ TEST(MatchExpressionParserLeafTest, TypeNull) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_TRUE(result.isOK()); + ASSERT_OK(result.getStatus()); ASSERT(!result.getValue()->matchesBSON(BSONObj())); ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5))); @@ -1071,7 +1426,7 @@ TEST(MatchExpressionParserLeafTest, TypeBad) { const CollatorInterface* collator = nullptr; StatusWithMatchExpression result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); - ASSERT_FALSE(result.isOK()); + ASSERT_NOT_OK(result.getStatus()); } TEST(MatchExpressionParserLeafTest, TypeBadString) { @@ -1264,6 +1619,20 @@ TEST(MatchExpressionParserLeafTest, ValidTypeCodesParseSuccessfully) { } } +TEST(MatchExpressionParserLeafTest, TypeWithConstantExprFails) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + BSONObj query = BSON("x" << BSON("$type" << BSON("$expr" + << "userVar"))); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(static_cast<int>(BSONType::NumberDouble))); + + StatusWithMatchExpression result = + MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator); + ASSERT_NOT_OK(result.getStatus()); +} + TEST(MatchExpressionParserTest, BitTestMatchExpressionValidMask) { const double k2Power53 = scalbn(1, 32); @@ -1947,4 +2316,36 @@ TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArrayValue) { collator) .getStatus()); } + +TEST(MatchExpressionParserLeafTest, BitTestWithConstantExprFails) { + boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + const CollatorInterface* collator = nullptr; + + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(BSON_ARRAY(1 << 5))); + + ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{$expr: 'userVar'}]}}"), + ExtensionsCallbackDisallowExtensions(), + collator, + expCtx) + .getStatus()); + + ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {$expr: 'userVar'}}}"), + ExtensionsCallbackDisallowExtensions(), + collator, + expCtx) + .getStatus()); + + ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {$expr: 'userVar'}}}"), + ExtensionsCallbackDisallowExtensions(), + collator, + expCtx) + .getStatus()); + + ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {$expr: 'userVar'}}}"), + ExtensionsCallbackDisallowExtensions(), + collator, + expCtx) + .getStatus()); } +} // namespace mongo diff --git a/src/mongo/db/matcher/expression_parser_tree.cpp b/src/mongo/db/matcher/expression_parser_tree.cpp index 91abc73cbfa..b7ba5964253 100644 --- a/src/mongo/db/matcher/expression_parser_tree.cpp +++ b/src/mongo/db/matcher/expression_parser_tree.cpp @@ -42,6 +42,7 @@ namespace mongo { Status MatchExpressionParser::_parseTreeList(const BSONObj& arr, ListOfMatchExpression* out, const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, bool topLevel) { if (arr.isEmpty()) return Status(ErrorCodes::BadValue, "$and/$or/$nor must be a nonempty array"); @@ -53,7 +54,7 @@ Status MatchExpressionParser::_parseTreeList(const BSONObj& arr, if (e.type() != Object) return Status(ErrorCodes::BadValue, "$or/$and/$nor entries need to be full objects"); - StatusWithMatchExpression sub = _parse(e.Obj(), collator, topLevel); + StatusWithMatchExpression sub = _parse(e.Obj(), collator, expCtx, topLevel); if (!sub.isOK()) return sub.getStatus(); @@ -62,12 +63,14 @@ Status MatchExpressionParser::_parseTreeList(const BSONObj& arr, return Status::OK(); } -StatusWithMatchExpression MatchExpressionParser::_parseNot(const char* name, - const BSONElement& e, - const CollatorInterface* collator, - bool topLevel) { +StatusWithMatchExpression MatchExpressionParser::_parseNot( + const char* name, + const BSONElement& e, + const CollatorInterface* collator, + const boost::intrusive_ptr<ExpressionContext>& expCtx, + bool topLevel) { if (e.type() == RegEx) { - StatusWithMatchExpression s = _parseRegexElement(name, e); + StatusWithMatchExpression s = _parseRegexElement(name, e, expCtx); if (!s.isOK()) return s; std::unique_ptr<NotMatchExpression> n = stdx::make_unique<NotMatchExpression>(); @@ -85,7 +88,7 @@ StatusWithMatchExpression MatchExpressionParser::_parseNot(const char* name, return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot be empty"); std::unique_ptr<AndMatchExpression> theAnd = stdx::make_unique<AndMatchExpression>(); - Status s = _parseSub(name, notObject, theAnd.get(), collator, topLevel); + Status s = _parseSub(name, notObject, theAnd.get(), collator, expCtx, topLevel); if (!s.isOK()) return StatusWithMatchExpression(s); diff --git a/src/mongo/db/matcher/expression_text_base.h b/src/mongo/db/matcher/expression_text_base.h index 0f75e40b412..65b38f90b43 100644 --- a/src/mongo/db/matcher/expression_text_base.h +++ b/src/mongo/db/matcher/expression_text_base.h @@ -52,6 +52,7 @@ public: static const bool kDiacriticSensitiveDefault; TextMatchExpressionBase(); + virtual ~TextMatchExpressionBase() {} /** * Returns a reference to the parsed text query that this TextMatchExpressionBase owns. diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp index 38c78d8ad30..250aa387c01 100644 --- a/src/mongo/db/pipeline/document_source_match.cpp +++ b/src/mongo/db/pipeline/document_source_match.cpp @@ -359,8 +359,8 @@ bool DocumentSourceMatch::isTextQuery(const BSONObj& query) { void DocumentSourceMatch::joinMatchWith(intrusive_ptr<DocumentSourceMatch> other) { _predicate = BSON("$and" << BSON_ARRAY(_predicate << other->getQuery())); - StatusWithMatchExpression status = uassertStatusOK( - MatchExpressionParser::parse(_predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator())); + StatusWithMatchExpression status = uassertStatusOK(MatchExpressionParser::parse( + _predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator(), pExpCtx)); _expression = std::move(status.getValue()); _dependencies = DepsTracker(_dependencies.getMetadataAvailable()); getDependencies(&_dependencies); @@ -506,8 +506,8 @@ void DocumentSourceMatch::addDependencies(DepsTracker* deps) const { DocumentSourceMatch::DocumentSourceMatch(const BSONObj& query, const intrusive_ptr<ExpressionContext>& pExpCtx) : DocumentSource(pExpCtx), _predicate(query.getOwned()), _isTextQuery(isTextQuery(query)) { - StatusWithMatchExpression status = uassertStatusOK( - MatchExpressionParser::parse(_predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator())); + StatusWithMatchExpression status = uassertStatusOK(MatchExpressionParser::parse( + _predicate, ExtensionsCallbackNoop(), pExpCtx->getCollator(), pExpCtx)); _expression = std::move(status.getValue()); getDependencies(&_dependencies); diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index 6e5ab270f46..d1bdaf6c983 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -1832,6 +1832,14 @@ intrusive_ptr<Expression> ExpressionFieldPath::optimize() { return ExpressionConstant::create(getExpressionContext(), Value()); } + if (Variables::isUserDefinedVariable(_variable) && + getExpressionContext()->variables.hasUserDefinedValue(_variable)) { + const auto val = getExpressionContext()->variables.getUserDefinedValue(_variable); + if (!val.missing()) { + return ExpressionConstant::create(getExpressionContext(), val); + } + } + return intrusive_ptr<Expression>(this); } diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index 22180869ccb..b05a1bc1515 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -2190,17 +2190,48 @@ public: } }; -/** No optimization is performed. */ -class Optimize { -public: - void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a"); - // An attempt to optimize returns the Expression itself. - ASSERT_EQUALS(expression, expression->optimize()); - } +TEST(FieldPath, NoOptimizationOnNormalPath) { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a"); + // An attempt to optimize returns the Expression itself. + ASSERT_EQUALS(expression, expression->optimize()); }; +TEST(FieldPath, OptimizeOnVariableWithConstantValue) { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value(123)); + + auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); + + auto optimizedExpr = expr->optimize(); + ASSERT_TRUE(dynamic_cast<ExpressionConstant*>(optimizedExpr.get())); +} + +TEST(FieldPath, NoOptimizationOnVariableWithNoValue) { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + expCtx->variablesParseState.defineVariable("userVar"); + + auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); + + auto optimizedExpr = expr->optimize(); + ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(optimizedExpr.get())); +} + +TEST(FieldPath, NoOptimizationOnVariableWithMissingValue) { + intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto varId = expCtx->variablesParseState.defineVariable("userVar"); + expCtx->variables.setValue(varId, Value()); + + auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); + + auto optimizedExpr = expr->optimize(); + ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(optimizedExpr.get())); +} + /** The field path itself is a dependency. */ class Dependencies { public: @@ -5254,7 +5285,6 @@ public: add<Constant::AddToBsonArray>(); add<FieldPath::Invalid>(); - add<FieldPath::Optimize>(); add<FieldPath::Dependencies>(); add<FieldPath::Missing>(); add<FieldPath::Present>(); diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp index f1222797f11..36aad7baf0d 100644 --- a/src/mongo/db/pipeline/pipeline_d.cpp +++ b/src/mongo/db/pipeline/pipeline_d.cpp @@ -420,7 +420,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExe const ExtensionsCallbackReal extensionsCallback(pExpCtx->opCtx, &nss); - auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback); + auto cq = CanonicalQuery::canonicalize(opCtx, std::move(qr), extensionsCallback, pExpCtx); if (!cq.isOK()) { // Return an error instead of uasserting, since there are cases where the combination of diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 0401460e60a..fb98ea45eeb 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -566,7 +566,8 @@ TEST(PipelineOptimizationTest, LookupDoesNotAbsorbUnwindOnSubfieldOfAsButStillMo TEST(PipelineOptimizationTest, MatchShouldDuplicateItselfBeforeRedact) { string inputPipe = "[{$redact: '$$PRUNE'}, {$match: {a: 1, b:12}}]"; - string outputPipe = "[{$match: {a: 1, b:12}}, {$redact: '$$PRUNE'}, {$match: {a: 1, b:12}}]"; + string outputPipe = + "[{$match: {a: 1, b:12}}, {$redact: {$const: 'prune'}}, {$match: {a: 1, b:12}}]"; assertPipelineOptimizesTo(inputPipe, outputPipe); } diff --git a/src/mongo/db/pipeline/variables.cpp b/src/mongo/db/pipeline/variables.cpp index 39b9130ed6e..ac713a37f5a 100644 --- a/src/mongo/db/pipeline/variables.cpp +++ b/src/mongo/db/pipeline/variables.cpp @@ -109,6 +109,15 @@ void Variables::setValue(Id id, const Value& value) { _valueList[id] = value; } +Value Variables::getUserDefinedValue(Variables::Id id) const { + invariant(isUserDefinedVariable(id)); + + uassert(40434, + str::stream() << "Requesting Variables::getValue with an out of range id: " << id, + static_cast<size_t>(id) < _valueList.size()); + return _valueList[id]; +} + Value Variables::getValue(Id id, const Document& root) const { if (id < 0) { // This is a reserved id for a builtin variable. @@ -122,10 +131,7 @@ Value Variables::getValue(Id id, const Document& root) const { } } - uassert(40434, - str::stream() << "Requesting Variables::getValue with an out of range id: " << id, - static_cast<size_t>(id) < _valueList.size()); - return _valueList[id]; + return getUserDefinedValue(id); } Document Variables::getDocument(Id id, const Document& root) const { diff --git a/src/mongo/db/pipeline/variables.h b/src/mongo/db/pipeline/variables.h index efbf115269f..4e487e811f4 100644 --- a/src/mongo/db/pipeline/variables.h +++ b/src/mongo/db/pipeline/variables.h @@ -64,6 +64,10 @@ public: static void uassertValidNameForUserWrite(StringData varName); static void uassertValidNameForUserRead(StringData varName); + static bool isUserDefinedVariable(Variables::Id id) { + return id >= 0; + } + // Ids for builtin variables. static constexpr Variables::Id kRootId = Id(-1); static constexpr Variables::Id kRemoveId = Id(-2); @@ -84,6 +88,20 @@ public: Value getValue(Variables::Id id, const Document& root) const; /** + * Gets the value of a user-defined variable. Should only be called when we know 'id' represents + * a user-defined variable. + */ + Value getUserDefinedValue(Variables::Id id) const; + + /** + * Returns whether a value for 'id' has been stored in this Variables instance. + */ + bool hasUserDefinedValue(Variables::Id id) const { + invariant(isUserDefinedVariable(id)); + return _valueList.size() > static_cast<size_t>(id); + } + + /** * Returns Document() for non-document values, but otherwise identical to getValue(). If the * 'id' provided represents the special ROOT variable, then we return 'root'. */ diff --git a/src/mongo/db/query/canonical_query.cpp b/src/mongo/db/query/canonical_query.cpp index ace19183ff5..a8e512c22d9 100644 --- a/src/mongo/db/query/canonical_query.cpp +++ b/src/mongo/db/query/canonical_query.cpp @@ -102,21 +102,26 @@ bool matchExpressionLessThan(const MatchExpression* lhs, const MatchExpression* // static StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize( - OperationContext* opCtx, const QueryMessage& qm, const ExtensionsCallback& extensionsCallback) { + OperationContext* opCtx, + const QueryMessage& qm, + const ExtensionsCallback& extensionsCallback, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { // Make QueryRequest. auto qrStatus = QueryRequest::fromLegacyQueryMessage(qm); if (!qrStatus.isOK()) { return qrStatus.getStatus(); } - return CanonicalQuery::canonicalize(opCtx, std::move(qrStatus.getValue()), extensionsCallback); + return CanonicalQuery::canonicalize( + opCtx, std::move(qrStatus.getValue()), extensionsCallback, expCtx); } // static StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize( OperationContext* opCtx, std::unique_ptr<QueryRequest> qr, - const ExtensionsCallback& extensionsCallback) { + const ExtensionsCallback& extensionsCallback, + const boost::intrusive_ptr<ExpressionContext>& expCtx) { auto qrStatus = qr->validate(); if (!qrStatus.isOK()) { return qrStatus; @@ -134,7 +139,7 @@ StatusWith<std::unique_ptr<CanonicalQuery>> CanonicalQuery::canonicalize( // Make MatchExpression. StatusWithMatchExpression statusWithMatcher = - MatchExpressionParser::parse(qr->getFilter(), extensionsCallback, collator.get()); + MatchExpressionParser::parse(qr->getFilter(), extensionsCallback, collator.get(), expCtx); if (!statusWithMatcher.isOK()) { return statusWithMatcher.getStatus(); } diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h index dfcbaf070f0..f2466fe0c66 100644 --- a/src/mongo/db/query/canonical_query.h +++ b/src/mongo/db/query/canonical_query.h @@ -48,26 +48,28 @@ public: * query (which will never be NULL). If parsing fails, returns an error Status. * * 'opCtx' must point to a valid OperationContext, but 'opCtx' does not need to outlive the - * returned - * CanonicalQuery. + * returned CanonicalQuery. * * Used for legacy find through the OP_QUERY message. */ static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize( OperationContext* opCtx, const QueryMessage& qm, - const ExtensionsCallback& extensionsCallback); + const ExtensionsCallback& extensionsCallback, + const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr); /** * If parsing succeeds, returns a std::unique_ptr<CanonicalQuery> representing the parsed * query (which will never be NULL). If parsing fails, returns an error Status. * * 'opCtx' must point to a valid OperationContext, but 'opCtx' does not need to outlive the - * returned - * CanonicalQuery. + * returned CanonicalQuery. */ static StatusWith<std::unique_ptr<CanonicalQuery>> canonicalize( - OperationContext* opCtx, std::unique_ptr<QueryRequest> qr, const ExtensionsCallback&); + OperationContext* opCtx, + std::unique_ptr<QueryRequest> qr, + const ExtensionsCallback&, + const boost::intrusive_ptr<ExpressionContext>& expCtx = nullptr); /** * For testing or for internal clients to use. diff --git a/src/mongo/db/update/addtoset_node_test.cpp b/src/mongo/db/update/addtoset_node_test.cpp index 816cccf4899..c8440764c38 100644 --- a/src/mongo/db/update/addtoset_node_test.cpp +++ b/src/mongo/db/update/addtoset_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using AddToSetNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -109,7 +108,7 @@ TEST_F(AddToSetNodeTest, ApplyFailsOnNonArray) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: 2}")); + mutablebson::Document doc(fromjson("{a: 2}")); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root()["a"])), @@ -124,7 +123,7 @@ TEST_F(AddToSetNodeTest, ApplyNonEach) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -141,7 +140,7 @@ TEST_F(AddToSetNodeTest, ApplyNonEachArray) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -158,7 +157,7 @@ TEST_F(AddToSetNodeTest, ApplyEach) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -175,7 +174,7 @@ TEST_F(AddToSetNodeTest, ApplyToEmptyArray) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -192,7 +191,7 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicateElementsToAdd) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -209,7 +208,7 @@ TEST_F(AddToSetNodeTest, ApplyDoNotAddExistingElements) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -226,7 +225,7 @@ TEST_F(AddToSetNodeTest, ApplyDoNotDeduplicateExistingElements) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0, 0]}")); + mutablebson::Document doc(fromjson("{a: [0, 0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -243,7 +242,7 @@ TEST_F(AddToSetNodeTest, ApplyNoElementsToAdd) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -260,7 +259,7 @@ TEST_F(AddToSetNodeTest, ApplyNoNonDuplicateElementsToAdd) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -277,7 +276,7 @@ TEST_F(AddToSetNodeTest, ApplyCreateArray) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -294,7 +293,7 @@ TEST_F(AddToSetNodeTest, ApplyCreateEmptyArrayIsNotNoop) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -311,7 +310,7 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicationOfElementsToAddRespectsCollation) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], &collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -328,7 +327,7 @@ TEST_F(AddToSetNodeTest, ApplyComparisonToExistingElementsRespectsCollation) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], &collator)); - Document doc(fromjson("{a: ['ABC']}")); + mutablebson::Document doc(fromjson("{a: ['ABC']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -349,7 +348,7 @@ TEST_F(AddToSetNodeTest, ApplyRespectsCollationFromSetCollator) { CollatorInterfaceMock::MockType::kToLowerString); node.setCollator(&caseInsensitiveCollator); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -387,7 +386,7 @@ TEST_F(AddToSetNodeTest, ApplyNestedArray) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a.1"], collator)); - Document doc(fromjson("{ _id : 1, a : [ 1, [ ] ] }")); + mutablebson::Document doc(fromjson("{ _id : 1, a : [ 1, [ ] ] }")); setPathTaken("a.1"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["1"])); @@ -404,7 +403,7 @@ TEST_F(AddToSetNodeTest, ApplyIndexesNotAffected) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -420,7 +419,7 @@ TEST_F(AddToSetNodeTest, ApplyNoIndexDataOrLogBuilder) { AddToSetNode node; ASSERT_OK(node.init(update["$addToSet"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); diff --git a/src/mongo/db/update/arithmetic_node_test.cpp b/src/mongo/db/update/arithmetic_node_test.cpp index 76855f66640..3a4d74121ea 100644 --- a/src/mongo/db/update/arithmetic_node_test.cpp +++ b/src/mongo/db/update/arithmetic_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using ArithmeticNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -116,7 +115,7 @@ TEST_F(ArithmeticNodeTest, ApplyIncNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -133,7 +132,7 @@ TEST_F(ArithmeticNodeTest, ApplyMulNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -150,7 +149,7 @@ TEST_F(ArithmeticNodeTest, ApplyRoundingNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 6.022e23}")); + mutablebson::Document doc(fromjson("{a: 6.022e23}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -167,7 +166,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyPathToCreate) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -184,7 +183,7 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b.c"], collator)); - Document doc(fromjson("{a: {d: 5}}")); + mutablebson::Document doc(fromjson("{a: {d: 5}}")); setPathToCreate("b.c"); setPathTaken("a"); addIndexedPath("a"); @@ -202,7 +201,7 @@ TEST_F(ArithmeticNodeTest, ApplyExtendPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: {c: 1}}")); + mutablebson::Document doc(fromjson("{a: {c: 1}}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a.b"); @@ -219,7 +218,7 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePathFromRoot) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{c: 5}")); + mutablebson::Document doc(fromjson("{c: 5}")); setPathToCreate("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -236,7 +235,7 @@ TEST_F(ArithmeticNodeTest, ApplyPositional) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.$"], collator)); - Document doc(fromjson("{a: [0, 1, 2]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2]}")); setPathTaken("a.1"); setMatchedField("1"); addIndexedPath("a"); @@ -254,7 +253,7 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathToInc) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -270,7 +269,7 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -289,7 +288,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoIndexDataNoLogBuilder) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -305,7 +304,7 @@ TEST_F(ArithmeticNodeTest, ApplyDoesNotAffectIndexes) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -321,7 +320,7 @@ TEST_F(ArithmeticNodeTest, IncTypePromotionIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: NumberInt(2)}")); + mutablebson::Document doc(fromjson("{a: NumberInt(2)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -337,7 +336,7 @@ TEST_F(ArithmeticNodeTest, MulTypePromotionIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a"], collator)); - Document doc(fromjson("{a: NumberInt(2)}")); + mutablebson::Document doc(fromjson("{a: NumberInt(2)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -353,7 +352,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromIntToDecimalIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: NumberInt(5)}")); + mutablebson::Document doc(fromjson("{a: NumberInt(5)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -370,7 +369,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromLongToDecimalIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: NumberLong(5)}")); + mutablebson::Document doc(fromjson("{a: NumberLong(5)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -387,7 +386,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromDoubleToDecimalIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 5.25}")); + mutablebson::Document doc(fromjson("{a: 5.25}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -404,7 +403,7 @@ TEST_F(ArithmeticNodeTest, ApplyPromoteToFloatingPoint) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: NumberLong(1)}")); + mutablebson::Document doc(fromjson("{a: NumberLong(1)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -420,7 +419,7 @@ TEST_F(ArithmeticNodeTest, IncrementedDecimalStaysDecimal) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: NumberDecimal(\"6.25\")}")); + mutablebson::Document doc(fromjson("{a: NumberDecimal(\"6.25\")}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -438,7 +437,7 @@ TEST_F(ArithmeticNodeTest, OverflowIntToLong) { ASSERT_OK(node.init(update["$inc"]["a"], collator)); const int initialValue = std::numeric_limits<int>::max(); - Document doc(BSON("a" << initialValue)); + mutablebson::Document doc(BSON("a" << initialValue)); ASSERT_EQUALS(mongo::NumberInt, doc.root()["a"].getType()); setPathTaken("a"); addIndexedPath("a"); @@ -457,7 +456,7 @@ TEST_F(ArithmeticNodeTest, UnderflowIntToLong) { ASSERT_OK(node.init(update["$inc"]["a"], collator)); const int initialValue = std::numeric_limits<int>::min(); - Document doc(BSON("a" << initialValue)); + mutablebson::Document doc(BSON("a" << initialValue)); ASSERT_EQUALS(mongo::NumberInt, doc.root()["a"].getType()); setPathTaken("a"); addIndexedPath("a"); @@ -475,8 +474,8 @@ TEST_F(ArithmeticNodeTest, IncModeCanBeReused) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc1(fromjson("{a: 1}")); - Document doc2(fromjson("{a: 2}")); + mutablebson::Document doc1(fromjson("{a: 1}")); + mutablebson::Document doc2(fromjson("{a: 2}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc1.root()["a"])); @@ -501,7 +500,7 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsInc) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{b: 6}")); + mutablebson::Document doc(fromjson("{b: 6}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -517,7 +516,7 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsMul) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a"], collator)); - Document doc(fromjson("{b: 6}")); + mutablebson::Document doc(fromjson("{b: 6}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -533,7 +532,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyDocument) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -549,7 +548,7 @@ TEST_F(ArithmeticNodeTest, ApplyIncToObjectFails) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{_id: 'test_object', a: {b: 1}}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: {b: 1}}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -565,7 +564,7 @@ TEST_F(ArithmeticNodeTest, ApplyIncToArrayFails) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{_id: 'test_object', a: []}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: []}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -581,7 +580,7 @@ TEST_F(ArithmeticNodeTest, ApplyIncToStringFails) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{_id: 'test_object', a: \"foo\"}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: \"foo\"}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -597,7 +596,7 @@ TEST_F(ArithmeticNodeTest, ApplyNewPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{b: 1}")); + mutablebson::Document doc(fromjson("{b: 1}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -613,7 +612,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyIndexData) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: 3}"), doc); @@ -628,7 +627,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpDottedPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -644,7 +643,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionOnDottedPathIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: {b: NumberInt(2)}}")); + mutablebson::Document doc(fromjson("{a: {b: NumberInt(2)}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -660,7 +659,7 @@ TEST_F(ArithmeticNodeTest, ApplyPathNotViableArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a:[{b:1}]}")); + mutablebson::Document doc(fromjson("{a:[{b:1}]}")); setPathToCreate("b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -675,7 +674,7 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceDottedPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -691,7 +690,7 @@ TEST_F(ArithmeticNodeTest, ApplyPromotionDottedPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{a: {b: NumberInt(3)}}")); + mutablebson::Document doc(fromjson("{a: {b: NumberInt(3)}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -707,7 +706,7 @@ TEST_F(ArithmeticNodeTest, ApplyDottedPathEmptyDoc) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root())); @@ -723,7 +722,7 @@ TEST_F(ArithmeticNodeTest, ApplyFieldWithDot) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.b"], collator)); - Document doc(fromjson("{'a.b':4}")); + mutablebson::Document doc(fromjson("{'a.b':4}")); setPathToCreate("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root())); @@ -739,7 +738,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpArrayIndex) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}")); setPathTaken("a.2.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -755,7 +754,8 @@ TEST_F(ArithmeticNodeTest, TypePromotionInArrayIsNotANoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: NumberInt(0)},{b: NumberInt(1)},{b: NumberInt(2)}]}")); + mutablebson::Document doc( + fromjson("{a: [{b: NumberInt(0)},{b: NumberInt(1)},{b: NumberInt(2)}]}")); setPathTaken("a.2.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -771,7 +771,7 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathThroughArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathToCreate("2.b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -786,7 +786,7 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceArrayIndex) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}")); setPathTaken("a.2.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -802,7 +802,7 @@ TEST_F(ArithmeticNodeTest, ApplyAppendArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1}]}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a"); @@ -819,7 +819,7 @@ TEST_F(ArithmeticNodeTest, ApplyPaddingArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a"); @@ -836,7 +836,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericObject) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: {b: 0}}")); + mutablebson::Document doc(fromjson("{a: {b: 0}}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a"); @@ -853,7 +853,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericField) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: {'2': {b: 1}}}")); + mutablebson::Document doc(fromjson("{a: {'2': {b: 1}}}")); setPathTaken("a.2.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -869,7 +869,7 @@ TEST_F(ArithmeticNodeTest, ApplyExtendNumericField) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: {'2': {c: 1}}}")); + mutablebson::Document doc(fromjson("{a: {'2': {c: 1}}}")); setPathToCreate("b"); setPathTaken("a.2"); addIndexedPath("a"); @@ -886,7 +886,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericFieldToEmptyObject) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a"); @@ -903,7 +903,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a"); @@ -920,7 +920,7 @@ TEST_F(ArithmeticNodeTest, ApplyLogDottedPath) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b:0}, {b:1}]}")); + mutablebson::Document doc(fromjson("{a: [{b:0}, {b:1}]}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -936,7 +936,7 @@ TEST_F(ArithmeticNodeTest, LogEmptyArray) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -952,7 +952,7 @@ TEST_F(ArithmeticNodeTest, LogEmptyObject) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kAdd); ASSERT_OK(node.init(update["$inc"]["a.2.b"], collator)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -968,7 +968,7 @@ TEST_F(ArithmeticNodeTest, ApplyDeserializedDocNotNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["b"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); // De-serialize the int. doc.root()["a"].setValueInt(1).transitional_ignore(); @@ -987,7 +987,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNoOp) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); // De-serialize the int. doc.root()["a"].setValueInt(2).transitional_ignore(); @@ -1006,7 +1006,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNoop) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a.b"], collator)); - Document doc{BSONObj()}; + mutablebson::Document doc{BSONObj()}; // De-serialize the int. doc.root().appendObject("a", BSON("b" << static_cast<int>(1))).transitional_ignore(); @@ -1025,7 +1025,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNotNoop) { ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); ASSERT_OK(node.init(update["$mul"]["a.b"], collator)); - Document doc{BSONObj()}; + mutablebson::Document doc{BSONObj()}; // De-serialize the int. doc.root().appendObject("a", BSON("b" << static_cast<int>(1))).transitional_ignore(); diff --git a/src/mongo/db/update/bit_node_test.cpp b/src/mongo/db/update/bit_node_test.cpp index 54db7ccdafb..868d064f66b 100644 --- a/src/mongo/db/update/bit_node_test.cpp +++ b/src/mongo/db/update/bit_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using BitNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -156,7 +155,7 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentAnd) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -171,7 +170,7 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentOr) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -186,7 +185,7 @@ TEST_F(BitNodeTest, ApplyAndLogEmptyDocumentXor) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -201,7 +200,7 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentAnd) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 0b0101)); + mutablebson::Document doc(BSON("a" << 0b0101)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -216,7 +215,7 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentOr) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 0b0101)); + mutablebson::Document doc(BSON("a" << 0b0101)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -231,7 +230,7 @@ TEST_F(BitNodeTest, ApplyAndLogSimpleDocumentXor) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 0b0101)); + mutablebson::Document doc(BSON("a" << 0b0101)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -246,7 +245,7 @@ TEST_F(BitNodeTest, ApplyShouldReportNoOp) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 1)); + mutablebson::Document doc(BSON("a" << 1)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_TRUE(result.noop); @@ -266,7 +265,7 @@ TEST_F(BitNodeTest, ApplyMultipleBitOps) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 0b1111111100000000)); + mutablebson::Document doc(BSON("a" << 0b1111111100000000)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -281,7 +280,7 @@ TEST_F(BitNodeTest, ApplyRepeatedBitOps) { BitNode node; ASSERT_OK(node.init(update["$bit"]["a"], collator)); - Document doc(BSON("a" << 0b11110000)); + mutablebson::Document doc(BSON("a" << 0b11110000)); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); diff --git a/src/mongo/db/update/compare_node_test.cpp b/src/mongo/db/update/compare_node_test.cpp index d69ac1c5d8b..37949aef2dc 100644 --- a/src/mongo/db/update/compare_node_test.cpp +++ b/src/mongo/db/update/compare_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using CompareNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -59,7 +58,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameNumber) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -76,7 +75,7 @@ TEST_F(CompareNodeTest, ApplyMinSameNumber) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -93,7 +92,7 @@ TEST_F(CompareNodeTest, ApplyMaxNumberIsLess) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -110,7 +109,7 @@ TEST_F(CompareNodeTest, ApplyMinNumberIsMore) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -127,7 +126,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameValInt) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 1.0}")); + mutablebson::Document doc(fromjson("{a: 1.0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -144,7 +143,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameValIntZero) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 0.0}")); + mutablebson::Document doc(fromjson("{a: 0.0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -161,7 +160,7 @@ TEST_F(CompareNodeTest, ApplyMinSameValIntZero) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], collator)); - Document doc(fromjson("{a: 0.0}")); + mutablebson::Document doc(fromjson("{a: 0.0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -178,7 +177,7 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMinNumber) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -195,7 +194,7 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMinNumber) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -212,7 +211,7 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMaxNumber) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -229,7 +228,7 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMaxNumber) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -246,7 +245,7 @@ TEST_F(CompareNodeTest, ApplyExistingDateMaxDate) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: {$date: 0}}")); + mutablebson::Document doc(fromjson("{a: {$date: 0}}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -263,7 +262,7 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxDoc) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -280,7 +279,7 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxNumber) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -297,7 +296,7 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollation) { CompareNode node(CompareNode::CompareMode::kMin); ASSERT_OK(node.init(update["$min"]["a"], &collator)); - Document doc(fromjson("{a: 'cbc'}")); + mutablebson::Document doc(fromjson("{a: 'cbc'}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -318,7 +317,7 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollationFromSetCollator) { CollatorInterfaceMock::MockType::kReverseString); node.setCollator(&reverseStringCollator); - Document doc(fromjson("{a: 'cbc'}")); + mutablebson::Document doc(fromjson("{a: 'cbc'}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -339,7 +338,7 @@ TEST_F(CompareNodeTest, ApplyMaxRespectsCollationFromSetCollator) { CollatorInterfaceMock::MockType::kReverseString); node.setCollator(&reverseStringCollator); - Document doc(fromjson("{a: 'cbc'}")); + mutablebson::Document doc(fromjson("{a: 'cbc'}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -377,7 +376,7 @@ TEST_F(CompareNodeTest, ApplyIndexesNotAffected) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -394,7 +393,7 @@ TEST_F(CompareNodeTest, ApplyNoIndexDataOrLogBuilder) { CompareNode node(CompareNode::CompareMode::kMax); ASSERT_OK(node.init(update["$max"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); diff --git a/src/mongo/db/update/current_date_node_test.cpp b/src/mongo/db/update/current_date_node_test.cpp index 7a5005b83d8..689ada219f6 100644 --- a/src/mongo/db/update/current_date_node_test.cpp +++ b/src/mongo/db/update/current_date_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using CurrentDateNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -128,7 +127,7 @@ TEST_F(CurrentDateNodeTest, ApplyTrue) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -152,7 +151,7 @@ TEST_F(CurrentDateNodeTest, ApplyFalse) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -176,7 +175,7 @@ TEST_F(CurrentDateNodeTest, ApplyDate) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -200,7 +199,7 @@ TEST_F(CurrentDateNodeTest, ApplyTimestamp) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -224,7 +223,7 @@ TEST_F(CurrentDateNodeTest, ApplyFieldDoesNotExist) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -248,7 +247,7 @@ TEST_F(CurrentDateNodeTest, ApplyIndexesNotAffected) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -272,7 +271,7 @@ TEST_F(CurrentDateNodeTest, ApplyNoIndexDataOrLogBuilder) { CurrentDateNode node; ASSERT_OK(node.init(update["$currentDate"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); diff --git a/src/mongo/db/update/log_builder.cpp b/src/mongo/db/update/log_builder.cpp index deddbab3840..173c8afb3f9 100644 --- a/src/mongo/db/update/log_builder.cpp +++ b/src/mongo/db/update/log_builder.cpp @@ -31,7 +31,6 @@ namespace mongo { -using mutablebson::Document; using mutablebson::Element; namespace str = mongoutils::str; @@ -49,7 +48,7 @@ inline Status LogBuilder::addToSection(Element newElt, Element* section, const c "LogBuilder: Invalid attempt to add a $set/$unset entry" "to a log with an existing object replacement"); - Document& doc = _logRoot.getDocument(); + mutablebson::Document& doc = _logRoot.getDocument(); // We should not already have an element with the section name under the root. dassert(_logRoot[sectionName] == doc.end()); diff --git a/src/mongo/db/update/object_replace_node_test.cpp b/src/mongo/db/update/object_replace_node_test.cpp index 69c3bbf6070..645a3e69ff3 100644 --- a/src/mongo/db/update/object_replace_node_test.cpp +++ b/src/mongo/db/update/object_replace_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using ObjectReplaceNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -50,7 +49,7 @@ TEST_F(ObjectReplaceNodeTest, Noop) { auto obj = fromjson("{a: 1, b: 2}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{a: 1, b: 2}")); + mutablebson::Document doc(fromjson("{a: 1, b: 2}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); @@ -63,7 +62,7 @@ TEST_F(ObjectReplaceNodeTest, ShouldNotCreateIdIfNoIdExistsAndNoneIsSpecified) { auto obj = fromjson("{a: 1, b: 2}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{c: 1, d: 2}")); + mutablebson::Document doc(fromjson("{c: 1, d: 2}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); @@ -76,7 +75,7 @@ TEST_F(ObjectReplaceNodeTest, ShouldPreserveIdOfExistingDocumentIfIdNotSpecified auto obj = fromjson("{a: 1, b: 2}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, c: 1, d: 2}")); + mutablebson::Document doc(fromjson("{_id: 0, c: 1, d: 2}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); @@ -89,7 +88,7 @@ TEST_F(ObjectReplaceNodeTest, ShouldSucceedWhenImmutableIdIsNotModified) { auto obj = fromjson("{_id: 0, a: 1, b: 2}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, c: 1, d: 2}")); + mutablebson::Document doc(fromjson("{_id: 0, c: 1, d: 2}")); addImmutablePath("_id"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -103,7 +102,7 @@ TEST_F(ObjectReplaceNodeTest, IdTimestampNotModified) { auto obj = fromjson("{_id: Timestamp(0,0)}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); @@ -116,7 +115,7 @@ TEST_F(ObjectReplaceNodeTest, NonIdTimestampsModified) { auto obj = fromjson("{a: Timestamp(0,0), b: Timestamp(0,0)}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); @@ -143,7 +142,7 @@ TEST_F(ObjectReplaceNodeTest, ComplexDoc) { auto obj = fromjson("{a: 1, b: [0, 1, 2], c: {d: 1}}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{a: 1, b: [0, 2, 2], e: []}")); + mutablebson::Document doc(fromjson("{a: 1, b: [0, 2, 2], e: []}")); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); @@ -156,7 +155,7 @@ TEST_F(ObjectReplaceNodeTest, CannotRemoveImmutablePath) { auto obj = fromjson("{_id: 0, c: 1}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, a: {b: 1}}")); + mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}")); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -169,7 +168,7 @@ TEST_F(ObjectReplaceNodeTest, IdFieldIsNotRemoved) { auto obj = fromjson("{a: 1}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, b: 1}")); + mutablebson::Document doc(fromjson("{_id: 0, b: 1}")); addImmutablePath("_id"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -183,7 +182,7 @@ TEST_F(ObjectReplaceNodeTest, CannotReplaceImmutablePathWithArrayField) { auto obj = fromjson("{_id: 0, a: [{b: 1}]}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, a: {b: 1}}")); + mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}")); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -196,7 +195,7 @@ TEST_F(ObjectReplaceNodeTest, CannotMakeImmutablePathArrayDescendant) { auto obj = fromjson("{_id: 0, a: [1]}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, a: {'0': 1}}")); + mutablebson::Document doc(fromjson("{_id: 0, a: {'0': 1}}")); addImmutablePath("a.0"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -209,7 +208,7 @@ TEST_F(ObjectReplaceNodeTest, CannotModifyImmutablePath) { auto obj = fromjson("{_id: 0, a: {b: 2}}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0, a: {b: 1}}")); + mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}")); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -222,7 +221,7 @@ TEST_F(ObjectReplaceNodeTest, CannotModifyImmutableId) { auto obj = fromjson("{_id: 1}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{_id: 0}")); + mutablebson::Document doc(fromjson("{_id: 0}")); addImmutablePath("_id"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -235,7 +234,7 @@ TEST_F(ObjectReplaceNodeTest, CanAddImmutableField) { auto obj = fromjson("{a: {b: 1}}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{c: 1}")); + mutablebson::Document doc(fromjson("{c: 1}")); addImmutablePath("a.b"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -249,7 +248,7 @@ TEST_F(ObjectReplaceNodeTest, CanAddImmutableId) { auto obj = fromjson("{_id: 0}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{c: 1}")); + mutablebson::Document doc(fromjson("{c: 1}")); addImmutablePath("_id"); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -263,7 +262,7 @@ TEST_F(ObjectReplaceNodeTest, CannotCreateDollarPrefixedNameWhenValidateForStora auto obj = fromjson("{a: {b: 1, $bad: 1}}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root())), UserException, @@ -275,7 +274,7 @@ TEST_F(ObjectReplaceNodeTest, CanCreateDollarPrefixedNameWhenValidateForStorageI auto obj = fromjson("{a: {b: 1, $bad: 1}}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setValidateForStorage(false); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); @@ -289,7 +288,7 @@ TEST_F(ObjectReplaceNodeTest, NoLogBuilder) { auto obj = fromjson("{a: 1}"); ObjectReplaceNode node(obj); - Document doc(fromjson("{b: 1}")); + mutablebson::Document doc(fromjson("{b: 1}")); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.noop); diff --git a/src/mongo/db/update/path_support_test.cpp b/src/mongo/db/update/path_support_test.cpp index 4a915bdf7d5..339781699e1 100644 --- a/src/mongo/db/update/path_support_test.cpp +++ b/src/mongo/db/update/path_support_test.cpp @@ -56,9 +56,9 @@ namespace { using namespace mongo; -using namespace mutablebson; using namespace pathsupport; using mongoutils::str::stream; +using mutablebson::Element; using std::unique_ptr; using std::string; @@ -66,7 +66,7 @@ class EmptyDoc : public mongo::unittest::Test { public: EmptyDoc() : _doc() {} - Document& doc() { + mutablebson::Document& doc() { return _doc; } @@ -83,7 +83,7 @@ public: } private: - Document _doc; + mutablebson::Document _doc; FieldRef _field; }; @@ -137,7 +137,7 @@ public: ASSERT_OK(root().appendInt("a", 1)); } - Document& doc() { + mutablebson::Document& doc() { return _doc; } @@ -153,7 +153,7 @@ public: } private: - Document _doc; + mutablebson::Document _doc; FieldRef _field; }; @@ -248,7 +248,7 @@ public: ASSERT_OK(root().pushBack(elemA)); } - Document& doc() { + mutablebson::Document& doc() { return _doc; } @@ -264,7 +264,7 @@ public: } private: - Document _doc; + mutablebson::Document _doc; FieldRef _field; }; @@ -363,7 +363,7 @@ public: ASSERT_OK(root().pushBack(elemB)); } - Document& doc() { + mutablebson::Document& doc() { return _doc; } @@ -380,7 +380,7 @@ public: } private: - Document _doc; + mutablebson::Document _doc; FieldRef _field; }; diff --git a/src/mongo/db/update/pull_node_test.cpp b/src/mongo/db/update/pull_node_test.cpp index f158b1c0678..9d3c101fba9 100644 --- a/src/mongo/db/update/pull_node_test.cpp +++ b/src/mongo/db/update/pull_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using PullNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -70,7 +69,7 @@ TEST_F(PullNodeTest, TargetNotFound) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -87,7 +86,7 @@ TEST_F(PullNodeTest, ApplyToStringFails) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: 'foo'}")); + mutablebson::Document doc(fromjson("{a: 'foo'}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -102,7 +101,7 @@ TEST_F(PullNodeTest, ApplyToObjectFails) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: {foo: 'bar'}}")); + mutablebson::Document doc(fromjson("{a: {foo: 'bar'}}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -117,7 +116,7 @@ TEST_F(PullNodeTest, ApplyToNonViablePathFails) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -134,7 +133,7 @@ TEST_F(PullNodeTest, ApplyToMissingElement) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b.c.d"], collator)); - Document doc(fromjson("{a: {b: {c: {}}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: {}}}}")); setPathToCreate("d"); setPathTaken("a.b.c"); addIndexedPath("a"); @@ -152,7 +151,7 @@ TEST_F(PullNodeTest, ApplyToEmptyArray) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -169,7 +168,7 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingNone) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [2, 3, 4, 5]}")); + mutablebson::Document doc(fromjson("{a: [2, 3, 4, 5]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -186,7 +185,7 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingOne) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2, 3]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -203,7 +202,7 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingSeveral) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 0, 2, 0, 3, 0, 4, 0, 5]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 0, 2, 0, 3, 0, 4, 0, 5]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -220,7 +219,7 @@ TEST_F(PullNodeTest, ApplyToArrayMatchingAll) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [0, -1, -2, -3, -4, -5]}")); + mutablebson::Document doc(fromjson("{a: [0, -1, -2, -3, -4, -5]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -237,7 +236,7 @@ TEST_F(PullNodeTest, ApplyNoIndexDataNoLogBuilder) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2, 3]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3]}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -255,7 +254,7 @@ TEST_F(PullNodeTest, ApplyWithCollation) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], &collator)); - Document doc(fromjson("{a: ['zaa', 'zcc', 'zbb', 'zee']}")); + mutablebson::Document doc(fromjson("{a: ['zaa', 'zcc', 'zbb', 'zee']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -272,7 +271,7 @@ TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectNonStringMatches) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], &collator)); - Document doc(fromjson("{a: [2, 1, 0, -1, -2, -3]}")); + mutablebson::Document doc(fromjson("{a: [2, 1, 0, -1, -2, -3]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -289,7 +288,7 @@ TEST_F(PullNodeTest, ApplyWithCollationDoesNotAffectRegexMatches) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], &collator)); - Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}")); + mutablebson::Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -306,7 +305,7 @@ TEST_F(PullNodeTest, ApplyStringLiteralMatchWithCollation) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], &collator)); - Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}")); + mutablebson::Document doc(fromjson("{a: ['b', 'a', 'aab', 'cb', 'bba']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -323,7 +322,7 @@ TEST_F(PullNodeTest, ApplyCollationDoesNotAffectNumberLiteralMatches) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], &collator)); - Document doc(fromjson("{a: ['a', 99, 'b', 2, 'c', 99, 'd']}")); + mutablebson::Document doc(fromjson("{a: ['a', 99, 'b', 2, 'c', 99, 'd']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -341,7 +340,7 @@ TEST_F(PullNodeTest, ApplyStringMatchAfterSetCollator) { ASSERT_OK(node.init(update["$pull"]["a"], collator)); // First without a collator. - Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); + mutablebson::Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -352,7 +351,7 @@ TEST_F(PullNodeTest, ApplyStringMatchAfterSetCollator) { // Now with a collator. CollatorInterfaceMock mockCollator(CollatorInterfaceMock::MockType::kAlwaysEqual); node.setCollator(&mockCollator); - Document doc2(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); + mutablebson::Document doc2(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); resetApplyParams(); setPathTaken("a"); result = node.apply(getApplyParams(doc2.root()["a"])); @@ -374,7 +373,7 @@ TEST_F(PullNodeTest, SetCollatorDoesNotAffectClone) { node.setCollator(&mockCollator); // The original node should now have collation. - Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); + mutablebson::Document doc(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_FALSE(result.noop); @@ -383,7 +382,7 @@ TEST_F(PullNodeTest, SetCollatorDoesNotAffectClone) { ASSERT_FALSE(doc.isInPlaceModeEnabled()); // The clone should have exact string matches (no collation). - Document doc2(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); + mutablebson::Document doc2(fromjson("{ a : ['a', 'b', 'c', 'd'] }")); resetApplyParams(); setPathTaken("a"); result = cloneNode->apply(getApplyParams(doc2.root()["a"])); @@ -403,7 +402,7 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching1) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b"], collator)); - Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); + mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -420,7 +419,7 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching2) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b"], collator)); - Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); + mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -437,7 +436,7 @@ TEST_F(PullNodeTest, ApplyComplexDocAndMatching3) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b"], collator)); - Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); + mutablebson::Document doc(fromjson("{a: {b: [{x: 1}, {y: 'y'}, {x: 2}, {z: 'z'}]}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -454,7 +453,8 @@ TEST_F(PullNodeTest, ApplyFullPredicateWithCollation) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a.b"], &collator)); - Document doc(fromjson("{a: {b: [{x: 'foo', y: 1}, {x: 'bar', y: 2}, {x: 'baz', y: 3}]}}")); + mutablebson::Document doc( + fromjson("{a: {b: [{x: 'foo', y: 1}, {x: 'bar', y: 2}, {x: 'baz', y: 3}]}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -471,7 +471,7 @@ TEST_F(PullNodeTest, ApplyScalarValueMod) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [1, 2, 1, 2, 1, 2]}")); + mutablebson::Document doc(fromjson("{a: [1, 2, 1, 2, 1, 2]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -488,7 +488,7 @@ TEST_F(PullNodeTest, ApplyObjectValueMod) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [{x: 1}, {y: 2}, {x: 1}, {y: 2}]}")); + mutablebson::Document doc(fromjson("{a: [{x: 1}, {y: 2}, {x: 1}, {y: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -505,7 +505,8 @@ TEST_F(PullNodeTest, DocumentationExample1) { PullNode node; ASSERT_OK(node.init(update["$pull"]["flags"], collator)); - Document doc(fromjson("{flags: ['vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce']}")); + mutablebson::Document doc( + fromjson("{flags: ['vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce']}")); setPathTaken("flags"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["flags"])); @@ -523,7 +524,7 @@ TEST_F(PullNodeTest, DocumentationExample2a) { PullNode node; ASSERT_OK(node.init(update["$pull"]["votes"], collator)); - Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}")); + mutablebson::Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}")); setPathTaken("votes"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["votes"])); @@ -540,7 +541,7 @@ TEST_F(PullNodeTest, DocumentationExample2b) { PullNode node; ASSERT_OK(node.init(update["$pull"]["votes"], collator)); - Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}")); + mutablebson::Document doc(fromjson("{votes: [3, 5, 6, 7, 7, 8]}")); setPathTaken("votes"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["votes"])); @@ -557,7 +558,7 @@ TEST_F(PullNodeTest, ApplyPullWithObjectValueToArrayWithNonObjectValue) { PullNode node; ASSERT_OK(node.init(update["$pull"]["a"], collator)); - Document doc(fromjson("{a: [{x: 1}, 2]}")); + mutablebson::Document doc(fromjson("{a: [{x: 1}, 2]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -574,7 +575,7 @@ TEST_F(PullNodeTest, CannotModifyImmutableField) { PullNode node; ASSERT_OK(node.init(update["$pull"]["_id.a"], collator)); - Document doc(fromjson("{_id: {a: [0, 1, 2]}}")); + mutablebson::Document doc(fromjson("{_id: {a: [0, 1, 2]}}")); setPathTaken("_id.a"); addImmutablePath("_id"); ASSERT_THROWS_CODE_AND_WHAT( @@ -590,7 +591,7 @@ TEST_F(PullNodeTest, SERVER_3988) { PullNode node; ASSERT_OK(node.init(update["$pull"]["y"], collator)); - Document doc(fromjson("{x: 1, y: [2, 3, 4, 'abc', 'xyz']}")); + mutablebson::Document doc(fromjson("{x: 1, y: [2, 3, 4, 'abc', 'xyz']}")); setPathTaken("y"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["y"])); diff --git a/src/mongo/db/update/pullall_node_test.cpp b/src/mongo/db/update/pullall_node_test.cpp index 1928b5f6223..4af970eb306 100644 --- a/src/mongo/db/update/pullall_node_test.cpp +++ b/src/mongo/db/update/pullall_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using PullAllNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -88,7 +87,7 @@ TEST_F(PullAllNodeTest, TargetNotFound) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["b"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathToCreate("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -105,7 +104,7 @@ TEST_F(PullAllNodeTest, TargetArrayElementNotFound) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a.2"], collator)); - Document doc(fromjson("{a: [1, 2]}")); + mutablebson::Document doc(fromjson("{a: [1, 2]}")); setPathToCreate("2"); setPathTaken("a"); addIndexedPath("a"); @@ -123,7 +122,7 @@ TEST_F(PullAllNodeTest, ApplyToNonArrayFails) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a.0"], collator)); - Document doc(fromjson("{a: [1, 2]}")); + mutablebson::Document doc(fromjson("{a: [1, 2]}")); setPathTaken("a.0"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"][0])), @@ -138,7 +137,7 @@ TEST_F(PullAllNodeTest, ApplyWithSingleNumber) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -155,7 +154,7 @@ TEST_F(PullAllNodeTest, ApplyNoIndexDataNoLogBuilder) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -171,7 +170,7 @@ TEST_F(PullAllNodeTest, ApplyWithElementNotPresentInArray) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -188,7 +187,7 @@ TEST_F(PullAllNodeTest, ApplyWithWithTwoElements) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -205,7 +204,7 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElements) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -222,7 +221,7 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsButOutOfOrder) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -239,7 +238,7 @@ TEST_F(PullAllNodeTest, ApplyWithAllArrayElementsAndThenSome) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); - Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [1, 'a', {r: 1, b: 2}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -256,7 +255,7 @@ TEST_F(PullAllNodeTest, ApplyWithCollator) { PullAllNode node; ASSERT_OK(node.init(update["$pullAll"]["a"], &collator)); - Document doc(fromjson("{a: ['foo', 'bar', 'baz']}")); + mutablebson::Document doc(fromjson("{a: ['foo', 'bar', 'baz']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -274,7 +273,7 @@ TEST_F(PullAllNodeTest, ApplyAfterSetCollator) { ASSERT_OK(node.init(update["$pullAll"]["a"], collator)); // First without a collator. - Document doc(fromjson("{a: ['foo', 'bar', 'baz']}")); + mutablebson::Document doc(fromjson("{a: ['foo', 'bar', 'baz']}")); setPathTaken("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); ASSERT_TRUE(result.noop); @@ -284,7 +283,7 @@ TEST_F(PullAllNodeTest, ApplyAfterSetCollator) { // Now with a collator. CollatorInterfaceMock mockCollator(CollatorInterfaceMock::MockType::kToLowerString); node.setCollator(&mockCollator); - Document doc2(fromjson("{a: ['foo', 'bar', 'baz']}")); + mutablebson::Document doc2(fromjson("{a: ['foo', 'bar', 'baz']}")); resetApplyParams(); setPathTaken("a"); result = node.apply(getApplyParams(doc2.root()["a"])); diff --git a/src/mongo/db/update/push_node_test.cpp b/src/mongo/db/update/push_node_test.cpp index a06b26484bd..ba9e988fb64 100644 --- a/src/mongo/db/update/push_node_test.cpp +++ b/src/mongo/db/update/push_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using PushNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -262,7 +261,7 @@ TEST_F(PushNodeTest, ApplyToNonArrayFails) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{_id: 'test_object', a: 1}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: 1}")); setPathTaken("a"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT( @@ -278,7 +277,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArray) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -295,7 +294,7 @@ TEST_F(PushNodeTest, ApplyToEmptyDocument) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -312,7 +311,7 @@ TEST_F(PushNodeTest, ApplyToArrayWithOneElement) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -329,7 +328,7 @@ TEST_F(PushNodeTest, ApplyToDottedPathElement) { PushNode node; ASSERT_OK(node.init(update["$push"]["choices.first.votes"], collator)); - Document doc( + mutablebson::Document doc( fromjson("{_id : 1 , " " question : 'a', " " choices: {first: { choice: 'b'}, " @@ -357,7 +356,7 @@ TEST_F(PushNodeTest, ApplySimpleEachToEmptyArray) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -374,7 +373,7 @@ TEST_F(PushNodeTest, ApplySimpleEachToEmptyDocument) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -391,7 +390,7 @@ TEST_F(PushNodeTest, ApplyMultipleEachToEmptyDocument) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -408,7 +407,7 @@ TEST_F(PushNodeTest, ApplySimpleEachToArrayWithOneElement) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -425,7 +424,7 @@ TEST_F(PushNodeTest, ApplyMultipleEachToArrayWithOneElement) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -442,7 +441,7 @@ TEST_F(PushNodeTest, ApplyEmptyEachToEmptyArray) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -459,7 +458,7 @@ TEST_F(PushNodeTest, ApplyEmptyEachToEmptyDocument) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -476,7 +475,7 @@ TEST_F(PushNodeTest, ApplyEmptyEachToArrayWithOneElement) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -493,7 +492,7 @@ TEST_F(PushNodeTest, ApplyToArrayWithSlice) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3]}")); + mutablebson::Document doc(fromjson("{a: [3]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -510,7 +509,7 @@ TEST_F(PushNodeTest, ApplyWithNumericSort) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3]}")); + mutablebson::Document doc(fromjson("{a: [3]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -527,7 +526,7 @@ TEST_F(PushNodeTest, ApplyWithReverseNumericSort) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3]}")); + mutablebson::Document doc(fromjson("{a: [3]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -544,7 +543,7 @@ TEST_F(PushNodeTest, ApplyWithMixedSort) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); + mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -561,7 +560,7 @@ TEST_F(PushNodeTest, ApplyWithReverseMixedSort) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); + mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -578,7 +577,7 @@ TEST_F(PushNodeTest, ApplyWithEmbeddedFieldSort) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); + mutablebson::Document doc(fromjson("{a: [3, 't', {b: 1}, {a: 1}]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -595,7 +594,7 @@ TEST_F(PushNodeTest, ApplySortWithCollator) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], &collator)); - Document doc(fromjson("{a: ['dd', 'fc', 'gb']}")); + mutablebson::Document doc(fromjson("{a: ['dd', 'fc', 'gb']}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -612,7 +611,7 @@ TEST_F(PushNodeTest, ApplySortAfterSetCollator) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: ['dd', 'fc', 'gb']}")); + mutablebson::Document doc(fromjson("{a: ['dd', 'fc', 'gb']}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -623,7 +622,7 @@ TEST_F(PushNodeTest, ApplySortAfterSetCollator) { // Now with a collator. CollatorInterfaceMock mockCollator(CollatorInterfaceMock::MockType::kReverseString); node.setCollator(&mockCollator); - Document doc2(fromjson("{a: ['dd', 'fc', 'gb']}")); + mutablebson::Document doc2(fromjson("{a: ['dd', 'fc', 'gb']}")); result = node.apply(getApplyParams(doc2.root()["a"])); ASSERT_FALSE(result.noop); ASSERT_EQUALS(fromjson("{a: ['ha', 'gb', 'fc', 'dd']}"), doc2); @@ -634,7 +633,7 @@ TEST_F(PushNodeTest, ApplySortAfterSetCollator) { // prints out the modifier when it observes a failure, which will help with diagnosis. void checkDocumentAndResult(BSONObj updateModifier, BSONObj expectedDocument, - const Document& actualDocument, + const mutablebson::Document& actualDocument, UpdateNode::ApplyResult applyResult) { if (expectedDocument == actualDocument && !applyResult.noop && !applyResult.indexesAffected) { // Check succeeded. @@ -671,7 +670,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithSliceValues) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -703,7 +702,7 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithSliceValues) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [2, 3]}")); + mutablebson::Document doc(fromjson("{a: [2, 3]}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -804,7 +803,7 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithSortAndSliceValues) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [{a: 2, b: 3}, {a: 3, b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{a: 2, b: 3}, {a: 3, b: 1}]}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -818,7 +817,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionZero) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -835,7 +834,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithPositionOne) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -852,7 +851,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithLargePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -869,7 +868,7 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithPositionZero) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -886,7 +885,7 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithLargePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -903,7 +902,7 @@ TEST_F(PushNodeTest, ApplyToEmptyArrayWithNegativePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -920,7 +919,7 @@ TEST_F(PushNodeTest, ApplyToSingletonArrayWithNegativePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -937,7 +936,7 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithNegativePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -954,7 +953,7 @@ TEST_F(PushNodeTest, ApplyToPopulatedArrayWithOutOfBoundsNegativePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -971,7 +970,7 @@ TEST_F(PushNodeTest, ApplyMultipleElementsPushWithNegativePosition) { PushNode node; ASSERT_OK(node.init(update["$push"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2, 3, 4]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); diff --git a/src/mongo/db/update/push_sorter_test.cpp b/src/mongo/db/update/push_sorter_test.cpp index 42cc0f3783d..611f4e80206 100644 --- a/src/mongo/db/update/push_sorter_test.cpp +++ b/src/mongo/db/update/push_sorter_test.cpp @@ -40,7 +40,6 @@ namespace mongo { namespace { -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::sortChildren; @@ -75,7 +74,7 @@ public: } private: - Document _doc; + mutablebson::Document _doc; BSONObj _objs[3]; size_t _size; }; diff --git a/src/mongo/db/update/rename_node_test.cpp b/src/mongo/db/update/rename_node_test.cpp index 84f46f0651f..a72485b7e23 100644 --- a/src/mongo/db/update/rename_node_test.cpp +++ b/src/mongo/db/update/rename_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using RenameNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -115,7 +114,7 @@ TEST_F(RenameNodeTest, SimpleNumberAtRoot) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2}")); + mutablebson::Document doc(fromjson("{a: 2}")); setPathToCreate("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -131,7 +130,7 @@ TEST_F(RenameNodeTest, ToExistsAtSameLevel) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2, b: 1}")); + mutablebson::Document doc(fromjson("{a: 2, b: 1}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -147,7 +146,7 @@ TEST_F(RenameNodeTest, ToAndFromHaveSameValue) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2, b: 2}")); + mutablebson::Document doc(fromjson("{a: 2, b: 2}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -163,7 +162,7 @@ TEST_F(RenameNodeTest, FromDottedElement) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.c"], collator)); - Document doc(fromjson("{a: {c: {d: 6}}, b: 1}")); + mutablebson::Document doc(fromjson("{a: {c: {d: 6}}, b: 1}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -179,7 +178,7 @@ TEST_F(RenameNodeTest, RenameToExistingNestedFieldDoesNotReorderFields) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["c.d"], collator)); - Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}")); setPathTaken("a.b.c"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"]["c"])); @@ -195,7 +194,7 @@ TEST_F(RenameNodeTest, MissingCompleteTo) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2, b: 1, c: {}}")); + mutablebson::Document doc(fromjson("{a: 2, b: 1, c: {}}")); setPathToCreate("r.d"); setPathTaken("c"); addIndexedPath("a"); @@ -212,7 +211,7 @@ TEST_F(RenameNodeTest, ToIsCompletelyMissing) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2}")); + mutablebson::Document doc(fromjson("{a: 2}")); setPathToCreate("b.c.d"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -228,7 +227,7 @@ TEST_F(RenameNodeTest, ToMissingDottedField) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: [{a:2, b:1}]}")); + mutablebson::Document doc(fromjson("{a: [{a:2, b:1}]}")); setPathToCreate("b.c.d"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -244,7 +243,7 @@ TEST_F(RenameNodeTest, MoveIntoArray) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["b"], collator)); - Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}")); setPathToCreate("2"); setPathTaken("a"); addIndexedPath("a"); @@ -261,7 +260,7 @@ TEST_F(RenameNodeTest, MoveIntoArrayNoId) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["b"], collator)); - Document doc(fromjson("{a: [1, 2], b: 2}")); + mutablebson::Document doc(fromjson("{a: [1, 2], b: 2}")); setPathToCreate("2"); setPathTaken("a"); addIndexedPath("a"); @@ -278,7 +277,7 @@ TEST_F(RenameNodeTest, MoveToArrayElement) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["b"], collator)); - Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2], b: 2}")); setPathTaken("a.1"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"]["1"])), @@ -294,7 +293,7 @@ TEST_F(RenameNodeTest, MoveOutOfArray) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.0"], collator)); - Document doc(fromjson("{_id: 'test_object', a: [1, 2]}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: [1, 2]}")); setPathToCreate("b"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), @@ -310,7 +309,7 @@ TEST_F(RenameNodeTest, MoveNonexistentEmbeddedFieldOut) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.a"], collator)); - Document doc(fromjson("{a: [{a: 1}, {b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [{a: 1}, {b: 2}]}")); setPathToCreate("b"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT( @@ -326,7 +325,7 @@ TEST_F(RenameNodeTest, MoveEmbeddedFieldOutWithElementNumber) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.0.a"], collator)); - Document doc(fromjson("{_id: 'test_object', a: [{a: 1}, {b: 2}]}")); + mutablebson::Document doc(fromjson("{_id: 'test_object', a: [{a: 1}, {b: 2}]}")); setPathToCreate("b"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), @@ -342,7 +341,7 @@ TEST_F(RenameNodeTest, ReplaceArrayField) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2, b: []}")); + mutablebson::Document doc(fromjson("{a: 2, b: []}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -358,7 +357,7 @@ TEST_F(RenameNodeTest, ReplaceWithArrayField) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: [], b: 2}")); + mutablebson::Document doc(fromjson("{a: [], b: 2}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -374,7 +373,7 @@ TEST_F(RenameNodeTest, CanRenameFromInvalidFieldName) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["$a"], collator)); - Document doc(fromjson("{$a: 2}")); + mutablebson::Document doc(fromjson("{$a: 2}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -390,7 +389,7 @@ TEST_F(RenameNodeTest, RenameWithoutLogBuilderOrIndexData) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 2}")); + mutablebson::Document doc(fromjson("{a: 2}")); setPathToCreate("b"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root())); @@ -404,7 +403,7 @@ TEST_F(RenameNodeTest, RenameFromNonExistentPathIsNoOp) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{b: 2}")); + mutablebson::Document doc(fromjson("{b: 2}")); setPathTaken("b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["b"])); @@ -420,7 +419,7 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.$id"], collator)); - Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); + mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); setPathToCreate("b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root())), UserException, @@ -434,7 +433,7 @@ TEST_F(RenameNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFa RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.$id"], collator)); - Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); + mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); setPathToCreate("b"); addIndexedPath("a"); setValidateForStorage(false); @@ -456,7 +455,7 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveImmutablePath) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathToCreate("c"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -472,7 +471,7 @@ TEST_F(RenameNodeTest, ApplyCannotRemovePrefixOfImmutablePath) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathToCreate("c"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -488,7 +487,7 @@ TEST_F(RenameNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {c: 1}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}")); setPathToCreate("d"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -504,7 +503,7 @@ TEST_F(RenameNodeTest, ApplyCanRemoveImmutablePathIfNoop) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {}}}")); + mutablebson::Document doc(fromjson("{a: {b: {}}}")); setPathToCreate("d"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -522,7 +521,7 @@ TEST_F(RenameNodeTest, ApplyCannotCreateDollarPrefixedField) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathToCreate("$bad"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root())), @@ -537,7 +536,7 @@ TEST_F(RenameNodeTest, ApplyCannotOverwriteImmutablePath) { RenameNode node; ASSERT_OK(node.init(update["$rename"]["a"], collator)); - Document doc(fromjson("{a: 0, b: 1}")); + mutablebson::Document doc(fromjson("{a: 0, b: 1}")); setPathTaken("b"); addImmutablePath("b"); ASSERT_THROWS_CODE_AND_WHAT( diff --git a/src/mongo/db/update/set_node_test.cpp b/src/mongo/db/update/set_node_test.cpp index 3d90d27b6c5..a7a6f793a10 100644 --- a/src/mongo/db/update/set_node_test.cpp +++ b/src/mongo/db/update/set_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using SetNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -65,7 +64,7 @@ TEST_F(SetNodeTest, ApplyNoOp) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -82,7 +81,7 @@ TEST_F(SetNodeTest, ApplyEmptyPathToCreate) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -99,7 +98,7 @@ TEST_F(SetNodeTest, ApplyCreatePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); - Document doc(fromjson("{a: {d: 5}}")); + mutablebson::Document doc(fromjson("{a: {d: 5}}")); setPathToCreate("b.c"); setPathTaken("a"); addIndexedPath("a"); @@ -117,7 +116,7 @@ TEST_F(SetNodeTest, ApplyCreatePathFromRoot) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{c: 5}")); + mutablebson::Document doc(fromjson("{c: 5}")); setPathToCreate("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -134,7 +133,7 @@ TEST_F(SetNodeTest, ApplyPositional) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.$"], collator)); - Document doc(fromjson("{a: [0, 1, 2]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2]}")); setPathTaken("a.1"); setMatchedField("1"); addIndexedPath("a"); @@ -152,7 +151,7 @@ TEST_F(SetNodeTest, ApplyNonViablePathToCreate) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -168,7 +167,7 @@ TEST_F(SetNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -187,7 +186,7 @@ TEST_F(SetNodeTest, ApplyNoIndexDataNoLogBuilder) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -203,7 +202,7 @@ TEST_F(SetNodeTest, ApplyDoesNotAffectIndexes) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -219,7 +218,7 @@ TEST_F(SetNodeTest, TypeChangeIsNotANoop) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: NumberInt(2)}")); + mutablebson::Document doc(fromjson("{a: NumberInt(2)}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -236,7 +235,7 @@ TEST_F(SetNodeTest, IdentityOpOnDeserializedIsNotANoOp) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: { b: NumberInt(0)}}")); + mutablebson::Document doc(fromjson("{a: { b: NumberInt(0)}}")); // Apply a mutation to the document that will make it non-serialized. doc.root()["a"]["b"].setValueInt(2).transitional_ignore(); @@ -255,7 +254,7 @@ TEST_F(SetNodeTest, ApplyEmptyDocument) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -271,7 +270,7 @@ TEST_F(SetNodeTest, ApplyInPlace) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -287,7 +286,7 @@ TEST_F(SetNodeTest, ApplyOverridePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -303,7 +302,7 @@ TEST_F(SetNodeTest, ApplyChangeType) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 'str'}")); + mutablebson::Document doc(fromjson("{a: 'str'}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -319,7 +318,7 @@ TEST_F(SetNodeTest, ApplyNewPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{b: 1}")); + mutablebson::Document doc(fromjson("{b: 1}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -335,7 +334,7 @@ TEST_F(SetNodeTest, ApplyLog) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); ASSERT_EQUALS(fromjson("{a: 2}"), doc); @@ -350,7 +349,7 @@ TEST_F(SetNodeTest, ApplyNoOpDottedPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -366,7 +365,7 @@ TEST_F(SetNodeTest, TypeChangeOnDottedPathIsNotANoOp) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: NumberLong(2)}}")); + mutablebson::Document doc(fromjson("{a: {b: NumberLong(2)}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -382,7 +381,7 @@ TEST_F(SetNodeTest, ApplyPathNotViable) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a:1}")); + mutablebson::Document doc(fromjson("{a:1}")); setPathToCreate("b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -397,7 +396,7 @@ TEST_F(SetNodeTest, ApplyPathNotViableArrray) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a:[{b:1}]}")); + mutablebson::Document doc(fromjson("{a:[{b:1}]}")); setPathToCreate("b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -412,7 +411,7 @@ TEST_F(SetNodeTest, ApplyInPlaceDottedPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -428,7 +427,7 @@ TEST_F(SetNodeTest, ApplyChangeTypeDottedPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 'str'}}")); + mutablebson::Document doc(fromjson("{a: {b: 'str'}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -444,7 +443,7 @@ TEST_F(SetNodeTest, ApplyChangePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: {c: 1}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}")); setPathTaken("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -460,7 +459,7 @@ TEST_F(SetNodeTest, ApplyExtendPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {c: 1}}")); + mutablebson::Document doc(fromjson("{a: {c: 1}}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a.b"); @@ -477,7 +476,7 @@ TEST_F(SetNodeTest, ApplyNewDottedPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{c: 1}")); + mutablebson::Document doc(fromjson("{c: 1}")); setPathToCreate("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root())); @@ -493,7 +492,7 @@ TEST_F(SetNodeTest, ApplyEmptyDoc) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root())); @@ -509,7 +508,7 @@ TEST_F(SetNodeTest, ApplyFieldWithDot) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{'a.b':4}")); + mutablebson::Document doc(fromjson("{'a.b':4}")); setPathToCreate("a.b"); addIndexedPath("a.b"); auto result = node.apply(getApplyParams(doc.root())); @@ -525,7 +524,7 @@ TEST_F(SetNodeTest, ApplyNoOpArrayIndex) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}")); setPathTaken("a.2.b"); addIndexedPath("a.2.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -541,7 +540,7 @@ TEST_F(SetNodeTest, TypeChangeInArrayIsNotANoOp) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2.0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 2.0}]}")); setPathTaken("a.2.b"); addIndexedPath("a.2.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -557,7 +556,7 @@ TEST_F(SetNodeTest, ApplyNonViablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); setPathToCreate("2.b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -572,7 +571,7 @@ TEST_F(SetNodeTest, ApplyInPlaceArrayIndex) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1},{b: 1}]}")); setPathTaken("a.2.b"); addIndexedPath("a.2.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -588,7 +587,7 @@ TEST_F(SetNodeTest, ApplyNormalArray) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0},{b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0},{b: 1}]}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a.2.b"); @@ -605,7 +604,7 @@ TEST_F(SetNodeTest, ApplyPaddingArray) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a.2.b"); @@ -622,7 +621,7 @@ TEST_F(SetNodeTest, ApplyNumericObject) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {b: 0}}")); + mutablebson::Document doc(fromjson("{a: {b: 0}}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a.2.b"); @@ -639,7 +638,7 @@ TEST_F(SetNodeTest, ApplyNumericField) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {'2': {b: 1}}}")); + mutablebson::Document doc(fromjson("{a: {'2': {b: 1}}}")); setPathTaken("a.2.b"); addIndexedPath("a.2.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"])); @@ -655,7 +654,7 @@ TEST_F(SetNodeTest, ApplyExtendNumericField) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {'2': {c: 1}}}")); + mutablebson::Document doc(fromjson("{a: {'2': {c: 1}}}")); setPathToCreate("b"); setPathTaken("a.2"); addIndexedPath("a.2.b"); @@ -672,7 +671,7 @@ TEST_F(SetNodeTest, ApplyEmptyObject) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a.2.b"); @@ -689,7 +688,7 @@ TEST_F(SetNodeTest, ApplyEmptyArray) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathToCreate("2.b"); setPathTaken("a"); addIndexedPath("a.2.b"); @@ -706,7 +705,7 @@ TEST_F(SetNodeTest, ApplyLogDottedPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: [{b:0}, {b:1}]}")); + mutablebson::Document doc(fromjson("{a: [{b:0}, {b:1}]}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -722,7 +721,7 @@ TEST_F(SetNodeTest, LogEmptyArray) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -738,7 +737,7 @@ TEST_F(SetNodeTest, LogEmptyObject) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.2.b"], collator)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); setPathToCreate("2.b"); setPathTaken("a"); node.apply(getApplyParams(doc.root()["a"])); @@ -754,7 +753,7 @@ TEST_F(SetNodeTest, ApplyNoOpComplex) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); - Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}")); + mutablebson::Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, d: 1}}]}}")); setPathTaken("a.1.b"); addIndexedPath("a.1.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["1"]["b"])); @@ -770,7 +769,7 @@ TEST_F(SetNodeTest, ApplySameStructure) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); - Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, xxx: 1}}]}}")); + mutablebson::Document doc(fromjson("{a: [{b: {c: 0, d: 0}}, {b: {c: 1, xxx: 1}}]}}")); setPathTaken("a.1.b"); addIndexedPath("a.1.b"); auto result = node.apply(getApplyParams(doc.root()["a"]["1"]["b"])); @@ -786,7 +785,7 @@ TEST_F(SetNodeTest, NonViablePathWithoutRepl) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathToCreate("1.b"); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -801,7 +800,7 @@ TEST_F(SetNodeTest, SingleFieldFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); - Document doc(fromjson("{_id:1, a: 1}")); + mutablebson::Document doc(fromjson("{_id:1, a: 1}")); setPathToCreate("1.b"); setPathTaken("a"); addIndexedPath("a.1.b"); @@ -819,7 +818,7 @@ TEST_F(SetNodeTest, SingleFieldNoIdFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.1.b"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathToCreate("1.b"); setPathTaken("a"); addIndexedPath("a.1.b"); @@ -837,7 +836,7 @@ TEST_F(SetNodeTest, NestedFieldFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator)); - Document doc(fromjson("{_id:1, a: {a: 1}}")); + mutablebson::Document doc(fromjson("{_id:1, a: {a: 1}}")); setPathToCreate("1.b"); setPathTaken("a.a"); addIndexedPath("a.a.1.b"); @@ -855,7 +854,7 @@ TEST_F(SetNodeTest, DoubleNestedFieldFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c.d"], collator)); - Document doc(fromjson("{_id:1, a: {b: {c: 1}}}")); + mutablebson::Document doc(fromjson("{_id:1, a: {b: {c: 1}}}")); setPathToCreate("d"); setPathTaken("a.b.c"); addIndexedPath("a.b.c.d"); @@ -873,7 +872,7 @@ TEST_F(SetNodeTest, NestedFieldNoIdFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.a.1.b"], collator)); - Document doc(fromjson("{a: {a: 1}}")); + mutablebson::Document doc(fromjson("{a: {a: 1}}")); setPathToCreate("1.b"); setPathTaken("a.a"); addIndexedPath("a.a.1.b"); @@ -891,7 +890,7 @@ TEST_F(SetNodeTest, ReplayArrayFieldNotAppendedIntermediateFromReplication) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.0.b"], collator)); - Document doc(fromjson("{_id: 0, a: [1, {b: [1]}]}")); + mutablebson::Document doc(fromjson("{_id: 0, a: [1, {b: [1]}]}")); setPathToCreate("b"); setPathTaken("a.0"); addIndexedPath("a.1.b"); @@ -909,7 +908,7 @@ TEST_F(SetNodeTest, Set6) { SetNode node; ASSERT_OK(node.init(update["$set"]["r.a"], collator)); - Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); + mutablebson::Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); setPathTaken("r.a"); addIndexedPath("r.a"); auto result = node.apply(getApplyParams(doc.root()["r"]["a"])); @@ -927,7 +926,7 @@ TEST_F(SetNodeTest, Set6FromRepl) { SetNode node; ASSERT_OK(node.init(update["$set"]["r.a"], collator)); - Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); + mutablebson::Document doc(fromjson("{_id: 1, r: {a:1, b:2}}")); setPathTaken("r.a"); addIndexedPath("r.a"); setFromReplication(true); @@ -949,7 +948,7 @@ TEST_F(SetNodeTest, ApplySetModToEphemeralDocument) { SetNode node; ASSERT_OK(node.init(update["$set"]["x"], collator)); - Document doc; + mutablebson::Document doc; Element x = doc.makeElementObject("x"); doc.root().pushBack(x).transitional_ignore(); Element a = doc.makeElementInt("a", 100); @@ -970,7 +969,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInsideSetElement) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root()["a"])), @@ -985,7 +984,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtStartOfPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["$bad.a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("$bad.a"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root())), @@ -1000,7 +999,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldInMiddleOfPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.$bad.b"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a.$bad.b"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root())), @@ -1015,7 +1014,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateDollarPrefixedFieldAtEndOfPath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.$bad"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a.$bad"); ASSERT_THROWS_CODE_AND_WHAT( node.apply(getApplyParams(doc.root())), @@ -1030,7 +1029,7 @@ TEST_F(SetNodeTest, ApplyCanCreateDollarPrefixedFieldNameWhenValidateForStorageI SetNode node; ASSERT_OK(node.init(update["$set"]["$bad"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("$bad"); addIndexedPath("$bad"); setValidateForStorage(false); @@ -1049,7 +1048,7 @@ TEST_F(SetNodeTest, ApplyCannotOverwriteImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a.b"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -1065,7 +1064,7 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a.b"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1084,7 +1083,7 @@ TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToRemoveImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -1100,7 +1099,7 @@ TEST_F(SetNodeTest, ApplyCannotOverwritePrefixToModifyImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -1116,7 +1115,7 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnPrefixOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1135,7 +1134,7 @@ TEST_F(SetNodeTest, ApplyCanOverwritePrefixToCreateImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1154,7 +1153,7 @@ TEST_F(SetNodeTest, ApplyCanOverwritePrefixOfImmutablePathIfNoopOnImmutablePath) SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{a: {b: 2}}")); + mutablebson::Document doc(fromjson("{a: {b: 2}}")); setPathTaken("a"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1173,7 +1172,7 @@ TEST_F(SetNodeTest, ApplyCannotOverwriteSuffixOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {c: 2}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 2}}}")); setPathTaken("a.b.c"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -1189,7 +1188,7 @@ TEST_F(SetNodeTest, ApplyCanPerformNoopOnSuffixOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {c: 2}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 2}}}")); setPathTaken("a.b.c"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1208,7 +1207,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateFieldAtEndOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {}}}")); + mutablebson::Document doc(fromjson("{a: {b: {}}}")); setPathToCreate("c"); setPathTaken("a.b"); addImmutablePath("a.b"); @@ -1225,7 +1224,7 @@ TEST_F(SetNodeTest, ApplyCannotCreateFieldBeyondEndOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {}}}")); + mutablebson::Document doc(fromjson("{a: {b: {}}}")); setPathToCreate("c"); setPathTaken("a.b"); addImmutablePath("a"); @@ -1242,7 +1241,7 @@ TEST_F(SetNodeTest, ApplyCanCreateImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a.b"], collator)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); setPathToCreate("b"); setPathTaken("a"); addImmutablePath("a.b"); @@ -1262,7 +1261,7 @@ TEST_F(SetNodeTest, ApplyCanCreatePrefixOfImmutablePath) { SetNode node; ASSERT_OK(node.init(update["$set"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addImmutablePath("a.b"); addIndexedPath("a"); @@ -1281,7 +1280,7 @@ TEST_F(SetNodeTest, ApplySetOnInsertIsNoopWhenInsertIsFalse) { SetNode node(UpdateNode::Context::kInsertOnly); ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -1298,7 +1297,7 @@ TEST_F(SetNodeTest, ApplySetOnInsertIsAppliedWhenInsertIsTrue) { SetNode node(UpdateNode::Context::kInsertOnly); ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); setInsert(true); addIndexedPath("a"); @@ -1316,7 +1315,7 @@ TEST_F(SetNodeTest, ApplySetOnInsertExistingPath) { SetNode node(UpdateNode::Context::kInsertOnly); ASSERT_OK(node.init(update["$setOnInsert"]["a"], collator)); - Document doc(fromjson("{a: 1}")); + mutablebson::Document doc(fromjson("{a: 1}")); setPathTaken("a"); setInsert(true); addIndexedPath("a"); diff --git a/src/mongo/db/update/unset_node_test.cpp b/src/mongo/db/update/unset_node_test.cpp index ad8f373e943..94be0fadb2d 100644 --- a/src/mongo/db/update/unset_node_test.cpp +++ b/src/mongo/db/update/unset_node_test.cpp @@ -41,7 +41,6 @@ namespace mongo { namespace { using UnsetNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; using mongo::mutablebson::countChildren; @@ -58,7 +57,7 @@ DEATH_TEST_F(UnsetNodeTest, ApplyToRootFails, "Invariant failure parent.ok()") { UnsetNode node; ASSERT_OK(node.init(update["$unset"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); node.apply(getApplyParams(doc.root())); } @@ -76,7 +75,7 @@ TEST_F(UnsetNodeTest, UnsetNoOp) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{b: 5}")); + mutablebson::Document doc(fromjson("{b: 5}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -93,7 +92,7 @@ TEST_F(UnsetNodeTest, UnsetNoOpDottedPath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -111,7 +110,7 @@ TEST_F(UnsetNodeTest, UnsetNoOpThroughArray) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b"], collator)); - Document doc(fromjson("{a:[{b:1}]}")); + mutablebson::Document doc(fromjson("{a:[{b:1}]}")); setPathToCreate("b"); setPathTaken("a"); addIndexedPath("a"); @@ -129,7 +128,7 @@ TEST_F(UnsetNodeTest, UnsetNoOpEmptyDoc) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setPathToCreate("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root())); @@ -146,7 +145,7 @@ TEST_F(UnsetNodeTest, UnsetTopLevelPath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -163,7 +162,7 @@ TEST_F(UnsetNodeTest, UnsetNestedPath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {c: 6}}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 6}}}}")); setPathTaken("a.b.c"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"]["c"])); @@ -180,7 +179,7 @@ TEST_F(UnsetNodeTest, UnsetObject) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b"], collator)); - Document doc(fromjson("{a: {b: {c: 6}}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 6}}}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -197,7 +196,7 @@ TEST_F(UnsetNodeTest, UnsetArrayElement) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.0"], collator)); - Document doc(fromjson("{a:[1], b:1}")); + mutablebson::Document doc(fromjson("{a:[1], b:1}")); setPathTaken("a.0"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["0"])); @@ -214,7 +213,7 @@ TEST_F(UnsetNodeTest, UnsetPositional) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.$"], collator)); - Document doc(fromjson("{a: [0, 1, 2]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2]}")); setPathTaken("a.1"); setMatchedField("1"); addIndexedPath("a"); @@ -232,7 +231,7 @@ TEST_F(UnsetNodeTest, UnsetEntireArray) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{a: [0, 1, 2]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 2]}")); setPathTaken("a"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -249,7 +248,7 @@ TEST_F(UnsetNodeTest, UnsetFromObjectInArray) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.0.b"], collator)); - Document doc(fromjson("{a: [{b: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 1}]}")); setPathTaken("a.0.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["0"]["b"])); @@ -266,7 +265,7 @@ TEST_F(UnsetNodeTest, CanUnsetInvalidField) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.$.$b"], collator)); - Document doc(fromjson("{b: 1, a: [{$b: 1}]}")); + mutablebson::Document doc(fromjson("{b: 1, a: [{$b: 1}]}")); setPathTaken("a.0.$b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["0"]["$b"])); @@ -283,7 +282,7 @@ TEST_F(UnsetNodeTest, ApplyNoIndexDataNoLogBuilder) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); setLogBuilderToNull(); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -299,7 +298,7 @@ TEST_F(UnsetNodeTest, ApplyDoesNotAffectIndexes) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); setPathTaken("a"); addIndexedPath("b"); auto result = node.apply(getApplyParams(doc.root()["a"])); @@ -316,7 +315,7 @@ TEST_F(UnsetNodeTest, ApplyFieldWithDot) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b"], collator)); - Document doc(fromjson("{'a.b':4, a: {b: 2}}")); + mutablebson::Document doc(fromjson("{'a.b':4, a: {b: 2}}")); setPathTaken("a.b"); addIndexedPath("a"); auto result = node.apply(getApplyParams(doc.root()["a"]["b"])); @@ -333,7 +332,7 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveRequiredPartOfDBRef) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.$id"], collator)); - Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); + mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); setPathTaken("a.$id"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"]["$id"])), UserException, @@ -347,7 +346,7 @@ TEST_F(UnsetNodeTest, ApplyCanRemoveRequiredPartOfDBRefIfValidateForStorageIsFal UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.$id"], collator)); - Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); + mutablebson::Document doc(fromjson("{a: {$ref: 'c', $id: 0}}")); setPathTaken("a.$id"); addIndexedPath("a"); setValidateForStorage(false); @@ -367,7 +366,7 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveImmutablePath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathTaken("a.b"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"]["b"])), @@ -382,7 +381,7 @@ TEST_F(UnsetNodeTest, ApplyCannotRemovePrefixOfImmutablePath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathTaken("a"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), @@ -397,7 +396,7 @@ TEST_F(UnsetNodeTest, ApplyCannotRemoveSuffixOfImmutablePath) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: {c: 1}}}")); + mutablebson::Document doc(fromjson("{a: {b: {c: 1}}}")); setPathTaken("a.b.c"); addImmutablePath("a.b"); ASSERT_THROWS_CODE_AND_WHAT( @@ -413,7 +412,7 @@ TEST_F(UnsetNodeTest, ApplyCanRemoveImmutablePathIfNoop) { UnsetNode node; ASSERT_OK(node.init(update["$unset"]["a.b.c"], collator)); - Document doc(fromjson("{a: {b: 1}}")); + mutablebson::Document doc(fromjson("{a: {b: 1}}")); setPathToCreate("c"); setPathTaken("a.b"); addImmutablePath("a.b"); diff --git a/src/mongo/db/update/update_array_node_test.cpp b/src/mongo/db/update/update_array_node_test.cpp index 60c5bfb4448..42087846813 100644 --- a/src/mongo/db/update/update_array_node_test.cpp +++ b/src/mongo/db/update/update_array_node_test.cpp @@ -42,7 +42,6 @@ namespace mongo { namespace { using UpdateArrayNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; TEST_F(UpdateArrayNodeTest, ApplyCreatePathFails) { @@ -60,7 +59,7 @@ TEST_F(UpdateArrayNodeTest, ApplyCreatePathFails) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT( root.apply(getApplyParams(doc.root())), @@ -84,7 +83,7 @@ TEST_F(UpdateArrayNodeTest, ApplyToNonArrayFails) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: {}}")); + mutablebson::Document doc(fromjson("{a: {}}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -107,7 +106,7 @@ TEST_F(UpdateArrayNodeTest, UpdateIsAppliedToAllMatchingElements) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0, 1, 0]}")); + mutablebson::Document doc(fromjson("{a: [0, 1, 0]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -134,7 +133,7 @@ DEATH_TEST_F(UpdateArrayNodeTest, arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{c: 0}, {c: 0}, {c: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{c: 0}, {c: 0}, {c: 1}]}")); doc.root()["a"]["1"]["c"].setValueInt(1).transitional_ignore(); doc.root()["a"]["2"]["c"].setValueInt(0).transitional_ignore(); addIndexedPath("a"); @@ -154,7 +153,7 @@ TEST_F(UpdateArrayNodeTest, UpdateForEmptyIdentifierIsAppliedToAllArrayElements) arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0, 0, 0]}")); + mutablebson::Document doc(fromjson("{a: [0, 0, 0]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -195,7 +194,7 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElement) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0, d: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0, d: 0}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -228,7 +227,7 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsUsingMergedChildr arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0}, {b: 0, c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0}, {b: 0, c: 0}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -269,7 +268,7 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementsWithoutMergedChil arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0, d: 1}, {b: 1, c: 0, d: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0, d: 1}, {b: 1, c: 0, d: 0}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -298,7 +297,7 @@ TEST_F(UpdateArrayNodeTest, ApplyMultipleUpdatesToArrayElementWithEmptyIdentifie arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -335,7 +334,7 @@ TEST_F(UpdateArrayNodeTest, ApplyNestedArrayUpdates) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{x: 0, b: [{c: 0, d: 0}]}]}")); + mutablebson::Document doc(fromjson("{a: [{x: 0, b: [{c: 0, d: 0}]}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -368,7 +367,7 @@ TEST_F(UpdateArrayNodeTest, ApplyUpdatesWithMergeConflictToArrayElementFails) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -399,7 +398,7 @@ TEST_F(UpdateArrayNodeTest, ApplyUpdatesWithEmptyIdentifiersWithMergeConflictToA arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: [0]}]}")); + mutablebson::Document doc(fromjson("{a: [{b: [0]}]}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -434,7 +433,7 @@ TEST_F(UpdateArrayNodeTest, ApplyNestedArrayUpdatesWithMergeConflictFails) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: [0], c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: [0], c: 0}]}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -457,7 +456,7 @@ TEST_F(UpdateArrayNodeTest, NoArrayElementsMatch) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [2, 2, 2]}")); + mutablebson::Document doc(fromjson("{a: [2, 2, 2]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); @@ -482,7 +481,7 @@ TEST_F(UpdateArrayNodeTest, UpdatesToAllArrayElementsAreNoops) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [1, 1, 1]}")); + mutablebson::Document doc(fromjson("{a: [1, 1, 1]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); @@ -507,7 +506,7 @@ TEST_F(UpdateArrayNodeTest, NoArrayElementAffectsIndexes) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{c: 0}, {c: 0}, {c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{c: 0}, {c: 0}, {c: 0}]}")); addIndexedPath("a.c"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); @@ -532,7 +531,7 @@ TEST_F(UpdateArrayNodeTest, WhenOneElementIsMatchedLogElementUpdateDirectly) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{c: 1}, {c: 0}, {c: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{c: 1}, {c: 0}, {c: 1}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -557,7 +556,7 @@ TEST_F(UpdateArrayNodeTest, WhenOneElementIsModifiedLogElement) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{c: 0, b: 0}, {c: 0}, {c: 1}]}")); + mutablebson::Document doc(fromjson("{a: [{c: 0, b: 0}, {c: 0}, {c: 1}]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -580,7 +579,7 @@ TEST_F(UpdateArrayNodeTest, ArrayUpdateOnEmptyArrayIsANoop) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); @@ -605,7 +604,7 @@ TEST_F(UpdateArrayNodeTest, ApplyPositionalInsideArrayUpdate) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: [0, 0], c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: [0, 0], c: 0}]}")); addIndexedPath("a"); setMatchedField("1"); auto result = root.apply(getApplyParams(doc.root())); @@ -631,7 +630,7 @@ TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateFromReplication) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); addIndexedPath("a"); setFromReplication(true); auto result = root.apply(getApplyParams(doc.root())); @@ -657,7 +656,7 @@ TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateNotFromReplication) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -680,7 +679,7 @@ TEST_F(UpdateArrayNodeTest, ApplyArrayUpdateWithoutLogBuilderOrIndexData) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0]}")); + mutablebson::Document doc(fromjson("{a: [0]}")); setLogBuilderToNull(); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp index f37074ce24b..02b6ae0e442 100644 --- a/src/mongo/db/update/update_driver_test.cpp +++ b/src/mongo/db/update/update_driver_test.cpp @@ -47,7 +47,6 @@ namespace mongo { namespace { -using mongo::mutablebson::Document; using mongoutils::str::stream; TEST(Parse, Normal) { @@ -163,7 +162,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) { const bool validateForStorage = true; const FieldRefSet emptyImmutablePaths; bool modified = false; - Document doc(fromjson("{a: 'cba'}")); + mutablebson::Document doc(fromjson("{a: 'cba'}")); driver.setCollator(&collator); driver .update(StringData(), @@ -195,7 +194,7 @@ public: _opCtx = _serviceContext.makeOperationContext(); } - Document& doc() { + mutablebson::Document& doc() { return _doc; } @@ -217,7 +216,7 @@ private: std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> _arrayFilters; std::unique_ptr<UpdateDriver> _driverOps; std::unique_ptr<UpdateDriver> _driverRepl; - Document _doc; + mutablebson::Document _doc; }; // Make name nicer to report diff --git a/src/mongo/db/update/update_object_node_test.cpp b/src/mongo/db/update/update_object_node_test.cpp index 018719b827a..6bb3d2c51c8 100644 --- a/src/mongo/db/update/update_object_node_test.cpp +++ b/src/mongo/db/update/update_object_node_test.cpp @@ -45,7 +45,6 @@ namespace mongo { namespace { using UpdateObjectNodeTest = UpdateNodeTest; -using mongo::mutablebson::Document; using mongo::mutablebson::Element; TEST(UpdateObjectNodeTest, InvalidPathFailsToParse) { @@ -1729,7 +1728,7 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateField) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); addIndexedPath("b"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1752,7 +1751,7 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingField) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 5}")); + mutablebson::Document doc(fromjson("{a: 5}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1793,7 +1792,7 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingAndNonexistingFields) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 0, c: 0}")); + mutablebson::Document doc(fromjson("{a: 0, c: 0}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1834,7 +1833,7 @@ TEST_F(UpdateObjectNodeTest, ApplyExistingNestedPaths) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: {b: 5, c: 5}, b: {d: 5, e: 5}}")); + mutablebson::Document doc(fromjson("{a: {b: 5, c: 5}, b: {d: 5, e: 5}}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1876,7 +1875,7 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateNestedPaths) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{z: 0}")); + mutablebson::Document doc(fromjson("{z: 0}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1912,7 +1911,7 @@ TEST_F(UpdateObjectNodeTest, ApplyCreateDeeplyNestedPaths) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{z: 0}")); + mutablebson::Document doc(fromjson("{z: 0}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1960,7 +1959,7 @@ TEST_F(UpdateObjectNodeTest, ChildrenShouldBeAppliedInAlphabeticalOrder) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{z: 0, a: 0}")); + mutablebson::Document doc(fromjson("{z: 0, a: 0}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -1989,7 +1988,7 @@ TEST_F(UpdateObjectNodeTest, CollatorShouldNotAffectUpdateOrder) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); addIndexedPath("abc"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -2024,7 +2023,7 @@ TEST_F(UpdateObjectNodeTest, ApplyNoop) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 5, b: 6, c: 7}")); + mutablebson::Document doc(fromjson("{a: 5, b: 6, c: 7}")); addIndexedPath("a"); addIndexedPath("b"); addIndexedPath("c"); @@ -2061,7 +2060,7 @@ TEST_F(UpdateObjectNodeTest, ApplySomeChildrenNoops) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 5, b: 0, c: 7}")); + mutablebson::Document doc(fromjson("{a: 5, b: 0, c: 7}")); addIndexedPath("a"); addIndexedPath("b"); addIndexedPath("c"); @@ -2086,7 +2085,7 @@ TEST_F(UpdateObjectNodeTest, ApplyBlockingElement) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -2113,7 +2112,7 @@ TEST_F(UpdateObjectNodeTest, ApplyBlockingElementFromReplication) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: 0}")); + mutablebson::Document doc(fromjson("{a: 0}")); addIndexedPath("a"); setFromReplication(true); auto result = root.apply(getApplyParams(doc.root())); @@ -2137,7 +2136,7 @@ TEST_F(UpdateObjectNodeTest, ApplyPositionalMissingMatchedField) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT( root.apply(getApplyParams(doc.root())), @@ -2165,7 +2164,7 @@ TEST_F(UpdateObjectNodeTest, ApplyMergePositionalChild) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0}]}")); setMatchedField("0"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2207,7 +2206,7 @@ TEST_F(UpdateObjectNodeTest, ApplyOrderMergedPositionalChild) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setMatchedField("1"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2238,7 +2237,7 @@ TEST_F(UpdateObjectNodeTest, ApplyMergeConflictWithPositionalChild) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setMatchedField("0"); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), @@ -2272,7 +2271,7 @@ TEST_F(UpdateObjectNodeTest, ApplyDoNotMergePositionalChild) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setMatchedField("1"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2308,7 +2307,7 @@ TEST_F(UpdateObjectNodeTest, ApplyPositionalChildLast) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{}")); + mutablebson::Document doc(fromjson("{}")); setMatchedField("2"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2338,7 +2337,7 @@ TEST_F(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0}]}")); setMatchedField("0"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2348,7 +2347,7 @@ TEST_F(UpdateObjectNodeTest, ApplyUseStoredMergedPositional) { ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_BSONOBJ_EQ(fromjson("{$set: {'a.0.b': 5, 'a.0.c': 6}}"), getLogDoc().getObject()); - Document doc2(fromjson("{a: [{b: 0, c: 0}]}")); + mutablebson::Document doc2(fromjson("{a: [{b: 0, c: 0}]}")); resetApplyParams(); setMatchedField("0"); addIndexedPath("a"); @@ -2385,7 +2384,7 @@ TEST_F(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 0, c: 0}, {c: 0, d: 0}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 0, c: 0}, {c: 0, d: 0}]}")); setMatchedField("0"); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); @@ -2396,7 +2395,7 @@ TEST_F(UpdateObjectNodeTest, ApplyDoNotUseStoredMergedPositional) { ASSERT_BSONOBJ_EQ(fromjson("{$set: {'a.0.b': 5, 'a.0.c': 6, 'a.1.d': 7}}"), getLogDoc().getObject()); - Document doc2(fromjson("{a: [{b: 0, c: 0}, {c: 0, d: 0}]}")); + mutablebson::Document doc2(fromjson("{a: [{b: 0, c: 0}, {c: 0, d: 0}]}")); resetApplyParams(); setMatchedField("1"); addIndexedPath("a"); @@ -2427,7 +2426,7 @@ TEST_F(UpdateObjectNodeTest, ApplyToArrayByIndexWithLeadingZero) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [0, 0, 0, 0, 0]}")); + mutablebson::Document doc(fromjson("{a: [0, 0, 0, 0, 0]}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -2462,7 +2461,7 @@ TEST_F(UpdateObjectNodeTest, ApplyMultipleArrayUpdates) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: []}")); + mutablebson::Document doc(fromjson("{a: []}")); addIndexedPath("a"); auto result = root.apply(getApplyParams(doc.root())); ASSERT_TRUE(result.indexesAffected); @@ -2487,7 +2486,7 @@ TEST_F(UpdateObjectNodeTest, ApplyUpdateToNonViablePathInArray) { arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: [{b: 1}, {b: 2}]}")); + mutablebson::Document doc(fromjson("{a: [{b: 1}, {b: 2}]}")); addIndexedPath("a"); ASSERT_THROWS_CODE_AND_WHAT(root.apply(getApplyParams(doc.root())), UserException, @@ -2514,7 +2513,7 @@ TEST_F(UpdateObjectNodeTest, SetAndPopModifiersWithCommonPrefixApplySuccessfully arrayFilters, foundIdentifiers)); - Document doc(fromjson("{a: {b: 3, c: [1, 2, 3, 4]}}")); + mutablebson::Document doc(fromjson("{a: {b: 3, c: [1, 2, 3, 4]}}")); auto result = root.apply(getApplyParams(doc.root())); ASSERT_FALSE(result.indexesAffected); ASSERT_FALSE(result.noop); diff --git a/src/mongo/dbtests/extensions_callback_real_test.cpp b/src/mongo/dbtests/extensions_callback_real_test.cpp index 7ea4e6a4af0..9c0105299d9 100644 --- a/src/mongo/dbtests/extensions_callback_real_test.cpp +++ b/src/mongo/dbtests/extensions_callback_real_test.cpp @@ -86,6 +86,15 @@ TEST_F(ExtensionsCallbackRealTest, TextNoIndex) { ASSERT_EQ(ErrorCodes::IndexNotFound, result.getStatus()); } +TEST_F(ExtensionsCallbackRealTest, TextRejectsExpr) { + BSONObj query = fromjson("{$text: {$expr: '$$userVar'}}"); + StatusWithMatchExpression result = + ExtensionsCallbackReal(&_opCtx, &_nss).parseText(query.firstElement()); + + ASSERT_NOT_OK(result.getStatus()); + ASSERT_EQ(ErrorCodes::NoSuchKey, result.getStatus()); +} + TEST_F(ExtensionsCallbackRealTest, TextBasic) { ASSERT_OK(dbtests::createIndex(&_opCtx, _nss.ns(), |