diff options
Diffstat (limited to 'src')
87 files changed, 1234 insertions, 2283 deletions
diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp index 168428779f7..a0cff1a7e81 100644 --- a/src/mongo/db/exec/collection_scan.cpp +++ b/src/mongo/db/exec/collection_scan.cpp @@ -72,9 +72,8 @@ CollectionScan::CollectionScan(OperationContext* opCtx, if (params.maxTs) { _endConditionBSON = BSON("$gte" << *(params.maxTs)); - _endCondition = stdx::make_unique<GTEMatchExpression>(); - invariantOK(_endCondition->init(repl::OpTime::kTimestampFieldName, - _endConditionBSON.firstElement())); + _endCondition = stdx::make_unique<GTEMatchExpression>(repl::OpTime::kTimestampFieldName, + _endConditionBSON.firstElement()); } } diff --git a/src/mongo/db/exec/geo_near.cpp b/src/mongo/db/exec/geo_near.cpp index 9da6af59370..d906efebc76 100644 --- a/src/mongo/db/exec/geo_near.cpp +++ b/src/mongo/db/exec/geo_near.cpp @@ -505,9 +505,7 @@ namespace { class TwoDPtInAnnulusExpression : public LeafMatchExpression { public: TwoDPtInAnnulusExpression(const R2Annulus& annulus, StringData twoDPath) - : LeafMatchExpression(INTERNAL_2D_POINT_IN_ANNULUS), _annulus(annulus) { - setPath(twoDPath).transitional_ignore(); - } + : LeafMatchExpression(INTERNAL_2D_POINT_IN_ANNULUS, twoDPath), _annulus(annulus) {} void serialize(BSONObjBuilder* out) const final { out->append("TwoDPtInAnnulusExpression", true); diff --git a/src/mongo/db/exec/oplogstart.cpp b/src/mongo/db/exec/oplogstart.cpp index 9b7659b3a13..4cb85047051 100644 --- a/src/mongo/db/exec/oplogstart.cpp +++ b/src/mongo/db/exec/oplogstart.cpp @@ -55,9 +55,8 @@ OplogStart::OplogStart(OperationContext* opCtx, _done(false), _collection(collection), _workingSet(ws), - _filterBSON(BSON("$lte" << timestamp)) { - invariantOK(_filter.init(repl::OpTime::kTimestampFieldName, _filterBSON.firstElement())); -} + _filterBSON(BSON("$lte" << timestamp)), + _filter(repl::OpTime::kTimestampFieldName, _filterBSON.firstElement()) {} PlanStage::StageState OplogStart::doWork(WorkingSetID* out) { // We do our (heavy) init in a work(), where work is expected. diff --git a/src/mongo/db/matcher/expression_algo.cpp b/src/mongo/db/matcher/expression_algo.cpp index 44791145805..e0575431de8 100644 --- a/src/mongo/db/matcher/expression_algo.cpp +++ b/src/mongo/db/matcher/expression_algo.cpp @@ -153,8 +153,7 @@ bool _isSubsetOf(const MatchExpression* lhs, const ComparisonMatchExpression* rh } for (BSONElement elem : ime->getEqualities()) { // Each element in the $in-array represents an equality predicate. - EqualityMatchExpression equality; - equality.init(lhs->path(), elem).transitional_ignore(); + EqualityMatchExpression equality(lhs->path(), elem); equality.setCollator(ime->getCollator()); if (!_isSubsetOf(&equality, rhs)) { return false; @@ -179,7 +178,7 @@ bool _isSubsetOf(const MatchExpression* lhs, const ExistsMatchExpression* rhs) { if (ComparisonMatchExpression::isComparisonMatchExpression(lhs)) { const ComparisonMatchExpression* cme = static_cast<const ComparisonMatchExpression*>(lhs); - // CompareMatchExpression::init() prohibits creating a match expression with EOO or + // The CompareMatchExpression constructor prohibits creating a match expression with EOO or // Undefined types, so only need to ensure that the value is not of type jstNULL. return cme->getData().type() != jstNULL; } diff --git a/src/mongo/db/matcher/expression_algo_test.cpp b/src/mongo/db/matcher/expression_algo_test.cpp index d1ec11137dd..49198f799dc 100644 --- a/src/mongo/db/matcher/expression_algo_test.cpp +++ b/src/mongo/db/matcher/expression_algo_test.cpp @@ -70,8 +70,8 @@ private: }; TEST(ExpressionAlgoIsSubsetOf, NullAndOmittedField) { - // Verify that ComparisonMatchExpression::init() prohibits creating a match expression with - // an Undefined type. + // Verify that the ComparisonMatchExpression constructor prohibits creating a match expression + // with an Undefined type. BSONObj undefined = fromjson("{a: undefined}"); boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); ASSERT_EQUALS(ErrorCodes::BadValue, diff --git a/src/mongo/db/matcher/expression_arity.h b/src/mongo/db/matcher/expression_arity.h index e6f71395941..a2b5734c1e1 100644 --- a/src/mongo/db/matcher/expression_arity.h +++ b/src/mongo/db/matcher/expression_arity.h @@ -93,13 +93,6 @@ public: } /** - * Takes ownership of the MatchExpressions in 'expressions'. - */ - void init(std::array<std::unique_ptr<MatchExpression>, nargs> expressions) { - _expressions = std::move(expressions); - } - - /** * The name of this MatchExpression. */ virtual StringData name() const = 0; @@ -121,7 +114,6 @@ public: * Clones this MatchExpression by recursively cloning each sub-expression. */ std::unique_ptr<MatchExpression> shallowClone() const final { - std::unique_ptr<T> clone = stdx::make_unique<T>(); std::array<std::unique_ptr<MatchExpression>, nargs> clonedExpressions; std::transform(_expressions.begin(), _expressions.end(), @@ -130,7 +122,7 @@ public: return orig ? orig->shallowClone() : std::unique_ptr<MatchExpression>(nullptr); }); - clone->_expressions = std::move(clonedExpressions); + std::unique_ptr<T> clone = stdx::make_unique<T>(std::move(clonedExpressions)); if (getTag()) { clone->setTag(getTag()->clone()); @@ -140,7 +132,12 @@ public: } protected: - explicit FixedArityMatchExpression(MatchType type) : MatchExpression(type) {} + /** + * Takes ownership of the MatchExpressions in 'expressions'. + */ + explicit FixedArityMatchExpression( + MatchType type, std::array<std::unique_ptr<MatchExpression>, nargs> expressions) + : MatchExpression(type), _expressions(std::move(expressions)) {} const auto& expressions() const { return _expressions; diff --git a/src/mongo/db/matcher/expression_array.cpp b/src/mongo/db/matcher/expression_array.cpp index 84c544df2bf..e4c9af9a024 100644 --- a/src/mongo/db/matcher/expression_array.cpp +++ b/src/mongo/db/matcher/expression_array.cpp @@ -67,10 +67,9 @@ bool ArrayMatchingMatchExpression::equivalent(const MatchExpression* other) cons // ------- -Status ElemMatchObjectMatchExpression::init(StringData path, MatchExpression* sub) { - _sub.reset(sub); - return setPath(path); -} +ElemMatchObjectMatchExpression::ElemMatchObjectMatchExpression(StringData path, + MatchExpression* sub) + : ArrayMatchingMatchExpression(ELEM_MATCH_OBJECT, path), _sub(sub) {} bool ElemMatchObjectMatchExpression::matchesArray(const BSONObj& anArray, MatchDetails* details) const { @@ -119,23 +118,20 @@ MatchExpression::ExpressionOptimizerFunc ElemMatchObjectMatchExpression::getOpti // ------- +ElemMatchValueMatchExpression::ElemMatchValueMatchExpression(StringData path, MatchExpression* sub) + : ArrayMatchingMatchExpression(ELEM_MATCH_VALUE, path) { + add(sub); +} + +ElemMatchValueMatchExpression::ElemMatchValueMatchExpression(StringData path) + : ArrayMatchingMatchExpression(ELEM_MATCH_VALUE, path) {} + ElemMatchValueMatchExpression::~ElemMatchValueMatchExpression() { for (unsigned i = 0; i < _subs.size(); i++) delete _subs[i]; _subs.clear(); } -Status ElemMatchValueMatchExpression::init(StringData path, MatchExpression* sub) { - init(path).transitional_ignore(); - add(sub); - return Status::OK(); -} - -Status ElemMatchValueMatchExpression::init(StringData path) { - return setPath(path); -} - - void ElemMatchValueMatchExpression::add(MatchExpression* sub) { verify(sub); _subs.push_back(sub); @@ -208,10 +204,8 @@ MatchExpression::ExpressionOptimizerFunc ElemMatchValueMatchExpression::getOptim // --------- -Status SizeMatchExpression::init(StringData path, int size) { - _size = size; - return setPath(path); -} +SizeMatchExpression::SizeMatchExpression(StringData path, int size) + : ArrayMatchingMatchExpression(SIZE, path), _size(size) {} bool SizeMatchExpression::matchesArray(const BSONObj& anArray, MatchDetails* details) const { if (_size < 0) diff --git a/src/mongo/db/matcher/expression_array.h b/src/mongo/db/matcher/expression_array.h index f4090c0a8b0..4cf54f43677 100644 --- a/src/mongo/db/matcher/expression_array.h +++ b/src/mongo/db/matcher/expression_array.h @@ -45,7 +45,10 @@ namespace mongo { */ class ArrayMatchingMatchExpression : public PathMatchExpression { public: - ArrayMatchingMatchExpression(MatchType matchType) : PathMatchExpression(matchType) {} + ArrayMatchingMatchExpression(MatchType matchType, StringData path) + : PathMatchExpression(matchType, path) { + setTraverseLeafArray(); + } virtual ~ArrayMatchingMatchExpression() {} @@ -71,15 +74,14 @@ public: class ElemMatchObjectMatchExpression : public ArrayMatchingMatchExpression { public: - ElemMatchObjectMatchExpression() : ArrayMatchingMatchExpression(ELEM_MATCH_OBJECT) {} - Status init(StringData path, MatchExpression* sub); + ElemMatchObjectMatchExpression(StringData path, MatchExpression* sub); bool matchesArray(const BSONObj& anArray, MatchDetails* details) const; virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ElemMatchObjectMatchExpression> e = - stdx::make_unique<ElemMatchObjectMatchExpression>(); - e->init(path(), _sub->shallowClone().release()).transitional_ignore(); + stdx::make_unique<ElemMatchObjectMatchExpression>(path(), + _sub->shallowClone().release()); if (getTag()) { e->setTag(getTag()->clone()); } @@ -118,19 +120,20 @@ private: class ElemMatchValueMatchExpression : public ArrayMatchingMatchExpression { public: - ElemMatchValueMatchExpression() : ArrayMatchingMatchExpression(ELEM_MATCH_VALUE) {} + /** + * This constructor takes ownership of 'sub.' + */ + ElemMatchValueMatchExpression(StringData path, MatchExpression* sub); + explicit ElemMatchValueMatchExpression(StringData path); virtual ~ElemMatchValueMatchExpression(); - Status init(StringData path); - Status init(StringData path, MatchExpression* sub); void add(MatchExpression* sub); bool matchesArray(const BSONObj& anArray, MatchDetails* details) const; virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<ElemMatchValueMatchExpression> e = - stdx::make_unique<ElemMatchValueMatchExpression>(); - e->init(path()).transitional_ignore(); + stdx::make_unique<ElemMatchValueMatchExpression>(path()); for (size_t i = 0; i < _subs.size(); ++i) { e->add(_subs[i]->shallowClone().release()); } @@ -166,12 +169,11 @@ private: class SizeMatchExpression : public ArrayMatchingMatchExpression { public: - SizeMatchExpression() : ArrayMatchingMatchExpression(SIZE) {} - Status init(StringData path, int size); + SizeMatchExpression(StringData path, int size); virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<SizeMatchExpression> e = stdx::make_unique<SizeMatchExpression>(); - e->init(path(), _size).transitional_ignore(); + std::unique_ptr<SizeMatchExpression> e = + stdx::make_unique<SizeMatchExpression>(path(), _size); if (getTag()) { e->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_array_test.cpp b/src/mongo/db/matcher/expression_array_test.cpp index 6b7d0c9a851..4d014818c2d 100644 --- a/src/mongo/db/matcher/expression_array_test.cpp +++ b/src/mongo/db/matcher/expression_array_test.cpp @@ -45,10 +45,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesElementSingle) { BSONObj baseOperand = BSON("b" << 5); BSONObj match = BSON("a" << BSON_ARRAY(BSON("b" << 5.0))); BSONObj notMatch = BSON("a" << BSON_ARRAY(BSON("b" << 6))); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("b", baseOperand["b"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("b", baseOperand["b"])); + ElemMatchObjectMatchExpression op("a", eq.release()); ASSERT(op.matchesSingleElement(match["a"])); ASSERT(!op.matchesSingleElement(notMatch["a"])); } @@ -57,10 +55,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesElementArray) { BSONObj baseOperand = BSON("1" << 5); BSONObj match = BSON("a" << BSON_ARRAY(BSON_ARRAY('s' << 5.0))); BSONObj notMatch = BSON("a" << BSON_ARRAY(BSON_ARRAY(5 << 6))); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("1", baseOperand["1"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("1", baseOperand["1"])); + ElemMatchObjectMatchExpression op("a", eq.release()); ASSERT(op.matchesSingleElement(match["a"])); ASSERT(!op.matchesSingleElement(notMatch["a"])); } @@ -73,20 +69,16 @@ TEST(ElemMatchObjectMatchExpression, MatchesElementMultiple) { BSONObj notMatch2 = BSON("a" << BSON_ARRAY(BSON("b" << 6 << "c" << 7))); BSONObj notMatch3 = BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(5 << 6)))); BSONObj match = BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(5 << 6) << "c" << 7))); - unique_ptr<ComparisonMatchExpression> eq1(new EqualityMatchExpression()); - ASSERT(eq1->init("b", baseOperand1["b"]).isOK()); - unique_ptr<ComparisonMatchExpression> eq2(new EqualityMatchExpression()); - ASSERT(eq2->init("b", baseOperand2["b"]).isOK()); - unique_ptr<ComparisonMatchExpression> eq3(new EqualityMatchExpression()); - ASSERT(eq3->init("c", baseOperand3["c"]).isOK()); + unique_ptr<ComparisonMatchExpression> eq1(new EqualityMatchExpression("b", baseOperand1["b"])); + unique_ptr<ComparisonMatchExpression> eq2(new EqualityMatchExpression("b", baseOperand2["b"])); + unique_ptr<ComparisonMatchExpression> eq3(new EqualityMatchExpression("c", baseOperand3["c"])); unique_ptr<AndMatchExpression> andOp(new AndMatchExpression()); andOp->add(eq1.release()); andOp->add(eq2.release()); andOp->add(eq3.release()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", andOp.release()).isOK()); + ElemMatchObjectMatchExpression op("a", andOp.release()); ASSERT(!op.matchesSingleElement(notMatch1["a"])); ASSERT(!op.matchesSingleElement(notMatch2["a"])); ASSERT(!op.matchesSingleElement(notMatch3["a"])); @@ -95,10 +87,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesElementMultiple) { TEST(ElemMatchObjectMatchExpression, MatchesNonArray) { BSONObj baseOperand = BSON("b" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("b", baseOperand["b"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("b", baseOperand["b"])); + ElemMatchObjectMatchExpression op("a", eq.release()); // Directly nested objects are not matched with $elemMatch. An intervening array is // required. ASSERT(!op.matchesBSON(BSON("a" << BSON("b" << 5)), NULL)); @@ -108,10 +98,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesNonArray) { TEST(ElemMatchObjectMatchExpression, MatchesArrayObject) { BSONObj baseOperand = BSON("b" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("b", baseOperand["b"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("b", baseOperand["b"])); + ElemMatchObjectMatchExpression op("a", eq.release()); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 5))), NULL)); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(4 << BSON("b" << 5))), NULL)); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSONObj() << BSON("b" << 5))), NULL)); @@ -120,10 +108,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesArrayObject) { TEST(ElemMatchObjectMatchExpression, MatchesMultipleNamedValues) { BSONObj baseOperand = BSON("c" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("c", baseOperand["c"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a.b", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("c", baseOperand["c"])); + ElemMatchObjectMatchExpression op("a.b", eq.release()); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(BSON("c" << 5))))), NULL)); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(BSON("c" << 1))) << BSON("b" << BSON_ARRAY(BSON("c" << 5))))), @@ -132,10 +118,8 @@ TEST(ElemMatchObjectMatchExpression, MatchesMultipleNamedValues) { TEST(ElemMatchObjectMatchExpression, ElemMatchKey) { BSONObj baseOperand = BSON("c" << 6); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("c", baseOperand["c"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a.b", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("c", baseOperand["c"])); + ElemMatchObjectMatchExpression op("a.b", eq.release()); MatchDetails details; details.requestElemMatchKey(); ASSERT(!op.matchesBSON(BSONObj(), &details)); @@ -161,10 +145,8 @@ TEST(ElemMatchObjectMatchExpression, Collation) { << "string"))); BSONObj notMatch = BSON("a" << BSON_ARRAY(BSON("b" << "string2"))); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("b", baseOperand["b"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("b", baseOperand["b"])); + ElemMatchObjectMatchExpression op("a", eq.release()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); op.setCollator(&collator); ASSERT(op.matchesSingleElement(match["a"])); @@ -189,10 +171,8 @@ TEST(ElemMatchValueMatchExpression, MatchesElementSingle) { BSONObj baseOperand = BSON("$gt" << 5); BSONObj match = BSON("a" << BSON_ARRAY(6)); BSONObj notMatch = BSON("a" << BSON_ARRAY(4)); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand["$gt"]).isOK()); - ElemMatchValueMatchExpression op; - ASSERT(op.init("a", gt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand["$gt"])); + ElemMatchValueMatchExpression op("a", gt.release()); ASSERT(op.matchesSingleElement(match["a"])); ASSERT(!op.matchesSingleElement(notMatch["a"])); } @@ -203,13 +183,10 @@ TEST(ElemMatchValueMatchExpression, MatchesElementMultiple) { BSONObj notMatch1 = BSON("a" << BSON_ARRAY(0 << 1)); BSONObj notMatch2 = BSON("a" << BSON_ARRAY(10 << 11)); BSONObj match = BSON("a" << BSON_ARRAY(0 << 5 << 11)); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand1["$gt"]).isOK()); - unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression()); - ASSERT(lt->init("", baseOperand2["$lt"]).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand1["$gt"])); + unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression("", baseOperand2["$lt"])); - ElemMatchValueMatchExpression op; - ASSERT(op.init("a").isOK()); + ElemMatchValueMatchExpression op("a"); op.add(gt.release()); op.add(lt.release()); @@ -220,10 +197,8 @@ TEST(ElemMatchValueMatchExpression, MatchesElementMultiple) { TEST(ElemMatchValueMatchExpression, MatchesNonArray) { BSONObj baseOperand = BSON("$gt" << 5); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand["$gt"]).isOK()); - ElemMatchObjectMatchExpression op; - ASSERT(op.init("a", gt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand["$gt"])); + ElemMatchObjectMatchExpression op("a", gt.release()); // Directly nested objects are not matched with $elemMatch. An intervening array is // required. ASSERT(!op.matchesBSON(BSON("a" << 6), NULL)); @@ -232,10 +207,8 @@ TEST(ElemMatchValueMatchExpression, MatchesNonArray) { TEST(ElemMatchValueMatchExpression, MatchesArrayScalar) { BSONObj baseOperand = BSON("$gt" << 5); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand["$gt"]).isOK()); - ElemMatchValueMatchExpression op; - ASSERT(op.init("a", gt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand["$gt"])); + ElemMatchValueMatchExpression op("a", gt.release()); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(4 << 6)), NULL)); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSONObj() << 7)), NULL)); @@ -243,10 +216,8 @@ TEST(ElemMatchValueMatchExpression, MatchesArrayScalar) { TEST(ElemMatchValueMatchExpression, MatchesMultipleNamedValues) { BSONObj baseOperand = BSON("$gt" << 5); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand["$gt"]).isOK()); - ElemMatchValueMatchExpression op; - ASSERT(op.init("a.b", gt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand["$gt"])); + ElemMatchValueMatchExpression op("a.b", gt.release()); ASSERT(op.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(6)))), NULL)); ASSERT(op.matchesBSON( BSON("a" << BSON_ARRAY(BSON("b" << BSON_ARRAY(4)) << BSON("b" << BSON_ARRAY(4 << 6)))), @@ -255,10 +226,8 @@ TEST(ElemMatchValueMatchExpression, MatchesMultipleNamedValues) { TEST(ElemMatchValueMatchExpression, ElemMatchKey) { BSONObj baseOperand = BSON("$gt" << 6); - unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression()); - ASSERT(gt->init("", baseOperand["$gt"]).isOK()); - ElemMatchValueMatchExpression op; - ASSERT(op.init("a.b", gt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> gt(new GTMatchExpression("", baseOperand["$gt"])); + ElemMatchValueMatchExpression op("a.b", gt.release()); MatchDetails details; details.requestElemMatchKey(); ASSERT(!op.matchesBSON(BSONObj(), &details)); @@ -292,37 +261,37 @@ TEST( ElemMatchValueMatchExpression, MatchesIndexKey ) { TEST(AndOfElemMatch, MatchesElement) { BSONObj baseOperanda1 = BSON("a" << 1); - unique_ptr<ComparisonMatchExpression> eqa1(new EqualityMatchExpression()); - ASSERT(eqa1->init("a", baseOperanda1["a"]).isOK()); + unique_ptr<ComparisonMatchExpression> eqa1( + new EqualityMatchExpression("a", baseOperanda1["a"])); BSONObj baseOperandb1 = BSON("b" << 1); - unique_ptr<ComparisonMatchExpression> eqb1(new EqualityMatchExpression()); - ASSERT(eqb1->init("b", baseOperandb1["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> eqb1( + new EqualityMatchExpression("b", baseOperandb1["b"])); unique_ptr<AndMatchExpression> and1(new AndMatchExpression()); and1->add(eqa1.release()); and1->add(eqb1.release()); // and1 = { a : 1, b : 1 } - unique_ptr<ElemMatchObjectMatchExpression> elemMatch1(new ElemMatchObjectMatchExpression()); - elemMatch1->init("x", and1.release()).transitional_ignore(); + unique_ptr<ElemMatchObjectMatchExpression> elemMatch1( + new ElemMatchObjectMatchExpression("x", and1.release())); // elemMatch1 = { x : { $elemMatch : { a : 1, b : 1 } } } BSONObj baseOperanda2 = BSON("a" << 2); - unique_ptr<ComparisonMatchExpression> eqa2(new EqualityMatchExpression()); - ASSERT(eqa2->init("a", baseOperanda2["a"]).isOK()); + unique_ptr<ComparisonMatchExpression> eqa2( + new EqualityMatchExpression("a", baseOperanda2["a"])); BSONObj baseOperandb2 = BSON("b" << 2); - unique_ptr<ComparisonMatchExpression> eqb2(new EqualityMatchExpression()); - ASSERT(eqb2->init("b", baseOperandb2["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> eqb2( + new EqualityMatchExpression("b", baseOperandb2["b"])); unique_ptr<AndMatchExpression> and2(new AndMatchExpression()); and2->add(eqa2.release()); and2->add(eqb2.release()); // and2 = { a : 2, b : 2 } - unique_ptr<ElemMatchObjectMatchExpression> elemMatch2(new ElemMatchObjectMatchExpression()); - elemMatch2->init("x", and2.release()).transitional_ignore(); + unique_ptr<ElemMatchObjectMatchExpression> elemMatch2( + new ElemMatchObjectMatchExpression("x", and2.release())); // elemMatch2 = { x : { $elemMatch : { a : 2, b : 2 } } } unique_ptr<AndMatchExpression> andOfEM(new AndMatchExpression()); @@ -349,29 +318,23 @@ TEST(AndOfElemMatch, MatchesElement) { TEST(AndOfElemMatch, Matches) { BSONObj baseOperandgt1 = BSON("$gt" << 1); - unique_ptr<ComparisonMatchExpression> gt1(new GTMatchExpression()); - ASSERT(gt1->init("", baseOperandgt1["$gt"]).isOK()); + unique_ptr<ComparisonMatchExpression> gt1(new GTMatchExpression("", baseOperandgt1["$gt"])); BSONObj baseOperandlt1 = BSON("$lt" << 10); - unique_ptr<ComparisonMatchExpression> lt1(new LTMatchExpression()); - ASSERT(lt1->init("", baseOperandlt1["$lt"]).isOK()); + unique_ptr<ComparisonMatchExpression> lt1(new LTMatchExpression("", baseOperandlt1["$lt"])); - unique_ptr<ElemMatchValueMatchExpression> elemMatch1(new ElemMatchValueMatchExpression()); - elemMatch1->init("x").transitional_ignore(); + unique_ptr<ElemMatchValueMatchExpression> elemMatch1(new ElemMatchValueMatchExpression("x")); elemMatch1->add(gt1.release()); elemMatch1->add(lt1.release()); // elemMatch1 = { x : { $elemMatch : { $gt : 1 , $lt : 10 } } } BSONObj baseOperandgt2 = BSON("$gt" << 101); - unique_ptr<ComparisonMatchExpression> gt2(new GTMatchExpression()); - ASSERT(gt2->init("", baseOperandgt2["$gt"]).isOK()); + unique_ptr<ComparisonMatchExpression> gt2(new GTMatchExpression("", baseOperandgt2["$gt"])); BSONObj baseOperandlt2 = BSON("$lt" << 110); - unique_ptr<ComparisonMatchExpression> lt2(new LTMatchExpression()); - ASSERT(lt2->init("", baseOperandlt2["$lt"]).isOK()); + unique_ptr<ComparisonMatchExpression> lt2(new LTMatchExpression("", baseOperandlt2["$lt"])); - unique_ptr<ElemMatchValueMatchExpression> elemMatch2(new ElemMatchValueMatchExpression()); - elemMatch2->init("x").transitional_ignore(); + unique_ptr<ElemMatchValueMatchExpression> elemMatch2(new ElemMatchValueMatchExpression("x")); elemMatch2->add(gt2.release()); elemMatch2->add(lt2.release()); // elemMatch2 = { x : { $elemMatch : { $gt : 101 , $lt : 110 } } } @@ -399,8 +362,7 @@ TEST(AndOfElemMatch, Matches) { TEST(SizeMatchExpression, MatchesElement) { BSONObj match = BSON("a" << BSON_ARRAY(5 << 6)); BSONObj notMatch = BSON("a" << BSON_ARRAY(5)); - SizeMatchExpression size; - ASSERT(size.init("", 2).isOK()); + SizeMatchExpression size("", 2); ASSERT(size.matchesSingleElement(match.firstElement())); ASSERT(!size.matchesSingleElement(notMatch.firstElement())); } @@ -411,31 +373,27 @@ TEST(SizeMatchExpression, MatchesNonArray) { << "z"); BSONObj numberValue = BSON("a" << 0); BSONObj arrayValue = BSON("a" << BSONArray()); - SizeMatchExpression size; - ASSERT(size.init("", 0).isOK()); + SizeMatchExpression size("", 0); ASSERT(!size.matchesSingleElement(stringValue.firstElement())); ASSERT(!size.matchesSingleElement(numberValue.firstElement())); ASSERT(size.matchesSingleElement(arrayValue.firstElement())); } TEST(SizeMatchExpression, MatchesArray) { - SizeMatchExpression size; - ASSERT(size.init("a", 2).isOK()); + SizeMatchExpression size("a", 2); ASSERT(size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL)); // Arrays are not unwound to look for matching subarrays. ASSERT(!size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5 << BSON_ARRAY(1 << 2))), NULL)); } TEST(SizeMatchExpression, MatchesNestedArray) { - SizeMatchExpression size; - ASSERT(size.init("a.2", 2).isOK()); + SizeMatchExpression size("a.2", 2); // A numerically referenced nested array is matched. ASSERT(size.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5 << BSON_ARRAY(1 << 2))), NULL)); } TEST(SizeMatchExpression, ElemMatchKey) { - SizeMatchExpression size; - ASSERT(size.init("a.b", 3).isOK()); + SizeMatchExpression size("a.b", 3); MatchDetails details; details.requestElemMatchKey(); ASSERT(!size.matchesBSON(BSON("a" << 1), &details)); @@ -449,13 +407,9 @@ TEST(SizeMatchExpression, ElemMatchKey) { } TEST(SizeMatchExpression, Equivalent) { - SizeMatchExpression e1; - SizeMatchExpression e2; - SizeMatchExpression e3; - - e1.init("a", 5).transitional_ignore(); - e2.init("a", 6).transitional_ignore(); - e3.init("v", 5).transitional_ignore(); + SizeMatchExpression e1("a", 5); + SizeMatchExpression e2("a", 6); + SizeMatchExpression e3("v", 5); ASSERT(e1.equivalent(&e1)); ASSERT(!e1.equivalent(&e2)); diff --git a/src/mongo/db/matcher/expression_geo.cpp b/src/mongo/db/matcher/expression_geo.cpp index 90ed78ecaa7..5cab016b9b9 100644 --- a/src/mongo/db/matcher/expression_geo.cpp +++ b/src/mongo/db/matcher/expression_geo.cpp @@ -329,13 +329,21 @@ Status GeoNearExpression::parseFrom(const BSONObj& obj) { // Geo queries we don't need an index to answer: geoWithin and geoIntersects // -Status GeoMatchExpression::init(StringData path, - const GeoExpression* query, - const BSONObj& rawObj) { - _query.reset(query); - _rawObj = rawObj; - return setPath(path); -} +/** +* Takes ownership of the passed-in GeoExpression. +*/ +GeoMatchExpression::GeoMatchExpression(StringData path, + const GeoExpression* query, + const BSONObj& rawObj) + : LeafMatchExpression(GEO, path), _rawObj(rawObj), _query(query), _canSkipValidation(false) {} + +/** +* Takes shared ownership of the passed-in GeoExpression. +*/ +GeoMatchExpression::GeoMatchExpression(StringData path, + std::shared_ptr<const GeoExpression> query, + const BSONObj& rawObj) + : LeafMatchExpression(GEO, path), _rawObj(rawObj), _query(query), _canSkipValidation(false) {} bool GeoMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { if (!e.isABSONObj()) @@ -398,9 +406,8 @@ bool GeoMatchExpression::equivalent(const MatchExpression* other) const { } std::unique_ptr<MatchExpression> GeoMatchExpression::shallowClone() const { - std::unique_ptr<GeoMatchExpression> next = stdx::make_unique<GeoMatchExpression>(); - next->init(path(), NULL, _rawObj).transitional_ignore(); - next->_query = _query; + std::unique_ptr<GeoMatchExpression> next = + stdx::make_unique<GeoMatchExpression>(path(), _query, _rawObj); next->_canSkipValidation = _canSkipValidation; if (getTag()) { next->setTag(getTag()->clone()); @@ -412,13 +419,15 @@ std::unique_ptr<MatchExpression> GeoMatchExpression::shallowClone() const { // Parse-only geo expressions: geoNear (formerly known as near). // -Status GeoNearMatchExpression::init(StringData path, - const GeoNearExpression* query, - const BSONObj& rawObj) { - _query.reset(query); - _rawObj = rawObj; - return setPath(path); -} +GeoNearMatchExpression::GeoNearMatchExpression(StringData path, + const GeoNearExpression* query, + const BSONObj& rawObj) + : LeafMatchExpression(GEO_NEAR, path), _rawObj(rawObj), _query(query) {} + +GeoNearMatchExpression::GeoNearMatchExpression(StringData path, + std::shared_ptr<const GeoNearExpression> query, + const BSONObj& rawObj) + : LeafMatchExpression(GEO_NEAR, path), _rawObj(rawObj), _query(query) {} bool GeoNearMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { @@ -455,9 +464,8 @@ bool GeoNearMatchExpression::equivalent(const MatchExpression* other) const { } std::unique_ptr<MatchExpression> GeoNearMatchExpression::shallowClone() const { - std::unique_ptr<GeoNearMatchExpression> next = stdx::make_unique<GeoNearMatchExpression>(); - next->init(path(), NULL, _rawObj).transitional_ignore(); - next->_query = _query; + std::unique_ptr<GeoNearMatchExpression> next = + stdx::make_unique<GeoNearMatchExpression>(path(), _query, _rawObj); if (getTag()) { next->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_geo.h b/src/mongo/db/matcher/expression_geo.h index 87b9624a5be..34b015484e6 100644 --- a/src/mongo/db/matcher/expression_geo.h +++ b/src/mongo/db/matcher/expression_geo.h @@ -78,15 +78,13 @@ private: class GeoMatchExpression : public LeafMatchExpression { public: - GeoMatchExpression() : LeafMatchExpression(GEO), _canSkipValidation(false) {} + GeoMatchExpression(StringData path, const GeoExpression* query, const BSONObj& rawObj); + GeoMatchExpression(StringData path, + std::shared_ptr<const GeoExpression> query, + const BSONObj& rawObj); virtual ~GeoMatchExpression() {} - /** - * Takes ownership of the passed-in GeoExpression. - */ - Status init(StringData path, const GeoExpression* query, const BSONObj& rawObj); - bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final; virtual void debugString(StringBuilder& debug, int level = 0) const; @@ -167,10 +165,12 @@ private: class GeoNearMatchExpression : public LeafMatchExpression { public: - GeoNearMatchExpression() : LeafMatchExpression(GEO_NEAR) {} - virtual ~GeoNearMatchExpression() {} + GeoNearMatchExpression(StringData path, const GeoNearExpression* query, const BSONObj& rawObj); + GeoNearMatchExpression(StringData path, + std::shared_ptr<const GeoNearExpression> query, + const BSONObj& rawObj); - Status init(StringData path, const GeoNearExpression* query, const BSONObj& rawObj); + virtual ~GeoNearMatchExpression() {} /** * Stub implementation that should never be called, since geoNear execution requires an diff --git a/src/mongo/db/matcher/expression_geo_test.cpp b/src/mongo/db/matcher/expression_geo_test.cpp index de7bd773c8a..082bcef790d 100644 --- a/src/mongo/db/matcher/expression_geo_test.cpp +++ b/src/mongo/db/matcher/expression_geo_test.cpp @@ -46,8 +46,7 @@ TEST(ExpressionGeoTest, Geo1) { std::unique_ptr<GeoExpression> gq(new GeoExpression); ASSERT_OK(gq->parseFrom(query["loc"].Obj())); - GeoMatchExpression ge; - ASSERT(ge.init("a", gq.release(), query).isOK()); + GeoMatchExpression ge("a", gq.release(), query); ASSERT(!ge.matchesBSON(fromjson("{a: [3,4]}"))); ASSERT(ge.matchesBSON(fromjson("{a: [4,4]}"))); @@ -63,8 +62,7 @@ TEST(ExpressionGeoTest, GeoNear1) { std::unique_ptr<GeoNearExpression> nq(new GeoNearExpression); ASSERT_OK(nq->parseFrom(query["loc"].Obj())); - GeoNearMatchExpression gne; - ASSERT(gne.init("a", nq.release(), query).isOK()); + GeoNearMatchExpression gne("a", nq.release(), query); // We can't match the data but we can make sure it was parsed OK. ASSERT_EQUALS(gne.getData().centroid->crs, SPHERE); @@ -76,8 +74,8 @@ std::unique_ptr<GeoMatchExpression> makeGeoMatchExpression(const BSONObj& locQue std::unique_ptr<GeoExpression> gq(new GeoExpression); ASSERT_OK(gq->parseFrom(locQuery)); - std::unique_ptr<GeoMatchExpression> ge = stdx::make_unique<GeoMatchExpression>(); - ASSERT_OK(ge->init("a", gq.release(), locQuery)); + std::unique_ptr<GeoMatchExpression> ge = + stdx::make_unique<GeoMatchExpression>("a", gq.release(), locQuery); return ge; } @@ -86,8 +84,8 @@ std::unique_ptr<GeoNearMatchExpression> makeGeoNearMatchExpression(const BSONObj std::unique_ptr<GeoNearExpression> nq(new GeoNearExpression); ASSERT_OK(nq->parseFrom(locQuery)); - std::unique_ptr<GeoNearMatchExpression> gne = stdx::make_unique<GeoNearMatchExpression>(); - ASSERT_OK(gne->init("a", nq.release(), locQuery)); + std::unique_ptr<GeoNearMatchExpression> gne = + stdx::make_unique<GeoNearMatchExpression>("a", nq.release(), locQuery); return gne; } diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp index ba0244b98a0..bde6be92d7d 100644 --- a/src/mongo/db/matcher/expression_leaf.cpp +++ b/src/mongo/db/matcher/expression_leaf.cpp @@ -47,29 +47,14 @@ namespace mongo { -bool ComparisonMatchExpression::equivalent(const MatchExpression* other) const { - if (other->matchType() != matchType()) - return false; - const ComparisonMatchExpression* realOther = - static_cast<const ComparisonMatchExpression*>(other); - - if (!CollatorInterface::collatorsMatch(_collator, realOther->_collator)) { - return false; - } - - const StringData::ComparatorInterface* stringComparator = nullptr; - BSONElementComparator eltCmp(BSONElementComparator::FieldNamesMode::kIgnore, stringComparator); - return path() == realOther->path() && eltCmp.evaluate(_rhs == realOther->_rhs); -} - -Status ComparisonMatchExpression::init(StringData path, const BSONElement& rhs) { - _rhs = rhs; - +ComparisonMatchExpression::ComparisonMatchExpression(MatchType type, + StringData path, + const BSONElement& rhs) + : LeafMatchExpression(type, path), _rhs(rhs) { invariant(_rhs); - if (_rhs.type() == BSONType::Undefined) { - return Status(ErrorCodes::BadValue, "cannot compare to undefined"); - } + uassert( + ErrorCodes::BadValue, "cannot compare to undefined", _rhs.type() != BSONType::Undefined); switch (matchType()) { case LT: @@ -79,10 +64,23 @@ Status ComparisonMatchExpression::init(StringData path, const BSONElement& rhs) case GTE: break; default: - return Status(ErrorCodes::BadValue, "bad match type for ComparisonMatchExpression"); + uasserted(ErrorCodes::BadValue, "bad match type for ComparisonMatchExpression"); } +} - return setPath(path); +bool ComparisonMatchExpression::equivalent(const MatchExpression* other) const { + if (other->matchType() != matchType()) + return false; + const ComparisonMatchExpression* realOther = + static_cast<const ComparisonMatchExpression*>(other); + + if (!CollatorInterface::collatorsMatch(_collator, realOther->_collator)) { + return false; + } + + const StringData::ComparatorInterface* stringComparator = nullptr; + BSONElementComparator eltCmp(BSONElementComparator::FieldNamesMode::kIgnore, stringComparator); + return path() == realOther->path() && eltCmp.evaluate(_rhs == realOther->_rhs); } bool ComparisonMatchExpression::matchesSingleElement(const BSONElement& e, @@ -221,7 +219,36 @@ inline pcrecpp::RE_Options flags2options(const char* flags) { return options; } -RegexMatchExpression::RegexMatchExpression() : LeafMatchExpression(REGEX) {} +RegexMatchExpression::RegexMatchExpression(StringData path, const BSONElement& e) + : LeafMatchExpression(REGEX, path), + _regex(e.regex()), + _flags(e.regexFlags()), + _re(new pcrecpp::RE(_regex.c_str(), flags2options(_flags.c_str()))) { + uassert(ErrorCodes::BadValue, "regex not a regex", e.type() == RegEx); + _init(); +} + +RegexMatchExpression::RegexMatchExpression(StringData path, StringData regex, StringData options) + : LeafMatchExpression(REGEX, path), + _regex(regex.toString()), + _flags(options.toString()), + _re(new pcrecpp::RE(_regex.c_str(), flags2options(_flags.c_str()))) { + _init(); +} + +void RegexMatchExpression::_init() { + uassert(ErrorCodes::BadValue, + "Regular expression cannot contain an embedded null byte", + _regex.find('\0') == std::string::npos); + + uassert(ErrorCodes::BadValue, + "Regular expression options string cannot contain an embedded null byte", + _flags.find('\0') == std::string::npos); + + uassert(ErrorCodes::BadValue, + str::stream() << "Regular expression is invalid: " << _re->error(), + _re->error().empty()); +} RegexMatchExpression::~RegexMatchExpression() {} @@ -234,37 +261,6 @@ bool RegexMatchExpression::equivalent(const MatchExpression* other) const { _flags == realOther->_flags; } - -Status RegexMatchExpression::init(StringData path, const BSONElement& e) { - if (e.type() != RegEx) - return Status(ErrorCodes::BadValue, "regex not a regex"); - return init(path, e.regex(), e.regexFlags()); -} - - -Status RegexMatchExpression::init(StringData path, StringData regex, StringData options) { - if (regex.find('\0') != std::string::npos) { - return Status(ErrorCodes::BadValue, - "Regular expression cannot contain an embedded null byte"); - } - - if (options.find('\0') != std::string::npos) { - return Status(ErrorCodes::BadValue, - "Regular expression options string cannot contain an embedded null byte"); - } - - _regex = regex.toString(); - _flags = options.toString(); - _re.reset(new pcrecpp::RE(_regex.c_str(), flags2options(_flags.c_str()))); - - if (!_re->error().empty()) { - return Status(ErrorCodes::BadValue, - str::stream() << "Regular expression is invalid: " << _re->error()); - } - - return setPath(path); -} - bool RegexMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { switch (e.type()) { case String: @@ -315,12 +311,9 @@ void RegexMatchExpression::shortDebugString(StringBuilder& debug) const { // --------- -Status ModMatchExpression::init(StringData path, int divisor, int remainder) { - if (divisor == 0) - return Status(ErrorCodes::BadValue, "divisor cannot be 0"); - _divisor = divisor; - _remainder = remainder; - return setPath(path); +ModMatchExpression::ModMatchExpression(StringData path, int divisor, int remainder) + : LeafMatchExpression(MOD, path), _divisor(divisor), _remainder(remainder) { + uassert(ErrorCodes::BadValue, "divisor cannot be 0", divisor != 0); } bool ModMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { @@ -356,9 +349,7 @@ bool ModMatchExpression::equivalent(const MatchExpression* other) const { // ------------------ -Status ExistsMatchExpression::init(StringData path) { - return setPath(path); -} +ExistsMatchExpression::ExistsMatchExpression(StringData path) : LeafMatchExpression(EXISTS, path) {} bool ExistsMatchExpression::matchesSingleElement(const BSONElement& e, MatchDetails* details) const { @@ -391,13 +382,13 @@ bool ExistsMatchExpression::equivalent(const MatchExpression* other) const { // ---- -Status InMatchExpression::init(StringData path) { - return setPath(path); -} +InMatchExpression::InMatchExpression(StringData path) + : LeafMatchExpression(MATCH_IN, path), + _eltCmp(BSONElementComparator::FieldNamesMode::kIgnore, _collator), + _equalitySet(_eltCmp.makeBSONEltFlatSet(_originalEqualityVector)) {} std::unique_ptr<MatchExpression> InMatchExpression::shallowClone() const { - auto next = stdx::make_unique<InMatchExpression>(); - next->init(path()).transitional_ignore(); + auto next = stdx::make_unique<InMatchExpression>(path()); next->setCollator(_collator); if (getTag()) { next->setTag(getTag()->clone()); @@ -552,18 +543,16 @@ MatchExpression::ExpressionOptimizerFunc InMatchExpression::getOptimizer() const auto& childRe = regexList.front(); invariant(!childRe->getTag()); - auto simplifiedExpression = stdx::make_unique<RegexMatchExpression>(); - invariantOK(simplifiedExpression->init( - expression->path(), childRe->getString(), childRe->getFlags())); + auto simplifiedExpression = stdx::make_unique<RegexMatchExpression>( + expression->path(), childRe->getString(), childRe->getFlags()); if (expression->getTag()) { simplifiedExpression->setTag(expression->getTag()->clone()); } - return std::move(simplifiedExpression); } else if (equalitySet.size() == 1 && regexList.empty()) { // Simplify IN of exactly one equality to be an EqualityMatchExpression. - auto simplifiedExpression = stdx::make_unique<EqualityMatchExpression>(); - invariantOK(simplifiedExpression->init(expression->path(), *(equalitySet.begin()))); + auto simplifiedExpression = stdx::make_unique<EqualityMatchExpression>( + expression->path(), *(equalitySet.begin())); simplifiedExpression->setCollator(collator); if (expression->getTag()) { simplifiedExpression->setTag(expression->getTag()->clone()); @@ -578,9 +567,10 @@ MatchExpression::ExpressionOptimizerFunc InMatchExpression::getOptimizer() const // ----------- -Status BitTestMatchExpression::init(StringData path, std::vector<uint32_t> bitPositions) { - _bitPositions = std::move(bitPositions); - +BitTestMatchExpression::BitTestMatchExpression(MatchType type, + StringData path, + std::vector<uint32_t> bitPositions) + : LeafMatchExpression(type, path), _bitPositions(std::move(bitPositions)) { // Process bit positions into bitmask. for (auto bitPosition : _bitPositions) { // Checking bits > 63 is just checking the sign bit, since we sign-extend numbers. For @@ -589,26 +579,23 @@ Status BitTestMatchExpression::init(StringData path, std::vector<uint32_t> bitPo bitPosition = std::min(bitPosition, 63U); _bitMask |= 1ULL << bitPosition; } - - return setPath(path); } -Status BitTestMatchExpression::init(StringData path, uint64_t bitMask) { - _bitMask = bitMask; - +BitTestMatchExpression::BitTestMatchExpression(MatchType type, StringData path, uint64_t bitMask) + : LeafMatchExpression(type, path), _bitMask(bitMask) { // Process bitmask into bit positions. for (int bit = 0; bit < 64; bit++) { if (_bitMask & (1ULL << bit)) { _bitPositions.push_back(bit); } } - - return setPath(path); } -Status BitTestMatchExpression::init(StringData path, - const char* bitMaskBinary, - uint32_t bitMaskLen) { +BitTestMatchExpression::BitTestMatchExpression(MatchType type, + StringData path, + const char* bitMaskBinary, + uint32_t bitMaskLen) + : LeafMatchExpression(type, path) { for (uint32_t byte = 0; byte < bitMaskLen; byte++) { char byteAt = bitMaskBinary[byte]; if (!byteAt) { @@ -631,8 +618,6 @@ Status BitTestMatchExpression::init(StringData path, } } } - - return setPath(path); } bool BitTestMatchExpression::needFurtherBitTests(bool isBitSet) const { diff --git a/src/mongo/db/matcher/expression_leaf.h b/src/mongo/db/matcher/expression_leaf.h index dd225c57763..77123742849 100644 --- a/src/mongo/db/matcher/expression_leaf.h +++ b/src/mongo/db/matcher/expression_leaf.h @@ -47,7 +47,10 @@ class CollatorInterface; class LeafMatchExpression : public PathMatchExpression { public: - explicit LeafMatchExpression(MatchType matchType) : PathMatchExpression(matchType) {} + explicit LeafMatchExpression(MatchType matchType, StringData path) + : PathMatchExpression(matchType, path) { + setTraverseLeafArray(); + } virtual ~LeafMatchExpression() {} @@ -77,9 +80,7 @@ public: */ class ComparisonMatchExpression : public LeafMatchExpression { public: - explicit ComparisonMatchExpression(MatchType type) : LeafMatchExpression(type) {} - - Status init(StringData path, const BSONElement& rhs); + explicit ComparisonMatchExpression(MatchType type, StringData path, const BSONElement& rhs); virtual ~ComparisonMatchExpression() {} @@ -136,10 +137,12 @@ private: class EqualityMatchExpression : public ComparisonMatchExpression { public: - EqualityMatchExpression() : ComparisonMatchExpression(EQ) {} + EqualityMatchExpression(StringData path, const BSONElement& rhs) + : ComparisonMatchExpression(EQ, path, rhs) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<EqualityMatchExpression>(); - invariantOK(e->init(path(), _rhs)); + std::unique_ptr<ComparisonMatchExpression> e = + stdx::make_unique<EqualityMatchExpression>(path(), _rhs); if (getTag()) { e->setTag(getTag()->clone()); } @@ -150,10 +153,12 @@ public: class LTEMatchExpression : public ComparisonMatchExpression { public: - LTEMatchExpression() : ComparisonMatchExpression(LTE) {} + LTEMatchExpression(StringData path, const BSONElement& rhs) + : ComparisonMatchExpression(LTE, path, rhs) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<LTEMatchExpression>(); - invariantOK(e->init(path(), _rhs)); + std::unique_ptr<ComparisonMatchExpression> e = + stdx::make_unique<LTEMatchExpression>(path(), _rhs); if (getTag()) { e->setTag(getTag()->clone()); } @@ -164,10 +169,12 @@ public: class LTMatchExpression : public ComparisonMatchExpression { public: - LTMatchExpression() : ComparisonMatchExpression(LT) {} + LTMatchExpression(StringData path, const BSONElement& rhs) + : ComparisonMatchExpression(LT, path, rhs) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<LTMatchExpression>(); - invariantOK(e->init(path(), _rhs)); + std::unique_ptr<ComparisonMatchExpression> e = + stdx::make_unique<LTMatchExpression>(path(), _rhs); if (getTag()) { e->setTag(getTag()->clone()); } @@ -178,10 +185,12 @@ public: class GTMatchExpression : public ComparisonMatchExpression { public: - GTMatchExpression() : ComparisonMatchExpression(GT) {} + GTMatchExpression(StringData path, const BSONElement& rhs) + : ComparisonMatchExpression(GT, path, rhs) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<GTMatchExpression>(); - invariantOK(e->init(path(), _rhs)); + std::unique_ptr<ComparisonMatchExpression> e = + stdx::make_unique<GTMatchExpression>(path(), _rhs); if (getTag()) { e->setTag(getTag()->clone()); } @@ -192,10 +201,12 @@ public: class GTEMatchExpression : public ComparisonMatchExpression { public: - GTEMatchExpression() : ComparisonMatchExpression(GTE) {} + GTEMatchExpression(StringData path, const BSONElement& rhs) + : ComparisonMatchExpression(GTE, path, rhs) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ComparisonMatchExpression> e = stdx::make_unique<GTEMatchExpression>(); - invariantOK(e->init(path(), _rhs)); + std::unique_ptr<ComparisonMatchExpression> e = + stdx::make_unique<GTEMatchExpression>(path(), _rhs); if (getTag()) { e->setTag(getTag()->clone()); } @@ -206,15 +217,13 @@ public: class RegexMatchExpression : public LeafMatchExpression { public: - RegexMatchExpression(); + RegexMatchExpression(StringData path, const BSONElement& e); + RegexMatchExpression(StringData path, StringData regex, StringData options); ~RegexMatchExpression(); - Status init(StringData path, StringData regex, StringData options); - Status init(StringData path, const BSONElement& e); - virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<RegexMatchExpression> e = stdx::make_unique<RegexMatchExpression>(); - invariantOK(e->init(path(), _regex, _flags)); + std::unique_ptr<RegexMatchExpression> e = + stdx::make_unique<RegexMatchExpression>(path(), _regex, _flags); if (getTag()) { e->setTag(getTag()->clone()); } @@ -245,6 +254,8 @@ private: return [](std::unique_ptr<MatchExpression> expression) { return expression; }; } + void _init(); + std::string _regex; std::string _flags; std::unique_ptr<pcrecpp::RE> _re; @@ -252,13 +263,11 @@ private: class ModMatchExpression : public LeafMatchExpression { public: - ModMatchExpression() : LeafMatchExpression(MOD) {} - - Status init(StringData path, int divisor, int remainder); + ModMatchExpression(StringData path, int divisor, int remainder); virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ModMatchExpression> m = stdx::make_unique<ModMatchExpression>(); - invariantOK(m->init(path(), _divisor, _remainder)); + std::unique_ptr<ModMatchExpression> m = + stdx::make_unique<ModMatchExpression>(path(), _divisor, _remainder); if (getTag()) { m->setTag(getTag()->clone()); } @@ -291,13 +300,10 @@ private: class ExistsMatchExpression : public LeafMatchExpression { public: - ExistsMatchExpression() : LeafMatchExpression(EXISTS) {} - - Status init(StringData path); + explicit ExistsMatchExpression(StringData path); virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<ExistsMatchExpression> e = stdx::make_unique<ExistsMatchExpression>(); - invariantOK(e->init(path())); + std::unique_ptr<ExistsMatchExpression> e = stdx::make_unique<ExistsMatchExpression>(path()); if (getTag()) { e->setTag(getTag()->clone()); } @@ -323,12 +329,7 @@ private: */ class InMatchExpression : public LeafMatchExpression { public: - InMatchExpression() - : LeafMatchExpression(MATCH_IN), - _eltCmp(BSONElementComparator::FieldNamesMode::kIgnore, _collator), - _equalitySet(_eltCmp.makeBSONEltFlatSet(_originalEqualityVector)) {} - - Status init(StringData path); + explicit InMatchExpression(StringData path); virtual std::unique_ptr<MatchExpression> shallowClone() const; @@ -401,16 +402,19 @@ private: */ class BitTestMatchExpression : public LeafMatchExpression { public: - explicit BitTestMatchExpression(MatchType type) : LeafMatchExpression(type) {} - virtual ~BitTestMatchExpression() {} - /** - * Initialize with either bit positions, a 64-bit numeric bitmask, or a char array + * Construct with either bit positions, a 64-bit numeric bitmask, or a char array * bitmask. */ - Status init(StringData path, std::vector<uint32_t> bitPositions); - Status init(StringData path, uint64_t bitMask); - Status init(StringData path, const char* bitMaskBinary, uint32_t bitMaskLen); + explicit BitTestMatchExpression(MatchType type, + StringData path, + std::vector<uint32_t> bitPositions); + explicit BitTestMatchExpression(MatchType type, StringData path, uint64_t bitMask); + explicit BitTestMatchExpression(MatchType type, + StringData path, + const char* bitMaskBinary, + uint32_t bitMaskLen); + virtual ~BitTestMatchExpression() {} bool matchesSingleElement(const BSONElement&, MatchDetails* details = nullptr) const final; @@ -428,18 +432,6 @@ public: return _bitPositions; } -protected: - /** - * Used to copy this match expression to another BitTestMatchExpression. Does not take - * ownership. - */ - void initClone(BitTestMatchExpression* clone) const { - invariantOK(clone->init(path(), _bitPositions)); - if (getTag()) { - clone->setTag(getTag()->clone()); - } - } - private: ExpressionOptimizerFunc getOptimizer() const final { return [](std::unique_ptr<MatchExpression> expression) { return expression; }; @@ -475,44 +467,84 @@ private: class BitsAllSetMatchExpression : public BitTestMatchExpression { public: - BitsAllSetMatchExpression() : BitTestMatchExpression(BITS_ALL_SET) {} + BitsAllSetMatchExpression(StringData path, std::vector<uint32_t> bitPositions) + : BitTestMatchExpression(BITS_ALL_SET, path, bitPositions) {} + + BitsAllSetMatchExpression(StringData path, uint64_t bitMask) + : BitTestMatchExpression(BITS_ALL_SET, path, bitMask) {} + + BitsAllSetMatchExpression(StringData path, const char* bitMaskBinary, uint32_t bitMaskLen) + : BitTestMatchExpression(BITS_ALL_SET, path, bitMaskBinary, bitMaskLen) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression = - stdx::make_unique<BitsAllSetMatchExpression>(); - initClone(bitTestMatchExpression.get()); + stdx::make_unique<BitsAllSetMatchExpression>(path(), getBitPositions()); + if (getTag()) { + bitTestMatchExpression->setTag(getTag()->clone()); + } return std::move(bitTestMatchExpression); } }; class BitsAllClearMatchExpression : public BitTestMatchExpression { public: - BitsAllClearMatchExpression() : BitTestMatchExpression(BITS_ALL_CLEAR) {} + BitsAllClearMatchExpression(StringData path, std::vector<uint32_t> bitPositions) + : BitTestMatchExpression(BITS_ALL_CLEAR, path, bitPositions) {} + + BitsAllClearMatchExpression(StringData path, uint64_t bitMask) + : BitTestMatchExpression(BITS_ALL_CLEAR, path, bitMask) {} + + BitsAllClearMatchExpression(StringData path, const char* bitMaskBinary, uint32_t bitMaskLen) + : BitTestMatchExpression(BITS_ALL_CLEAR, path, bitMaskBinary, bitMaskLen) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression = - stdx::make_unique<BitsAllClearMatchExpression>(); - initClone(bitTestMatchExpression.get()); + stdx::make_unique<BitsAllClearMatchExpression>(path(), getBitPositions()); + if (getTag()) { + bitTestMatchExpression->setTag(getTag()->clone()); + } return std::move(bitTestMatchExpression); } }; class BitsAnySetMatchExpression : public BitTestMatchExpression { public: - BitsAnySetMatchExpression() : BitTestMatchExpression(BITS_ANY_SET) {} + BitsAnySetMatchExpression(StringData path, std::vector<uint32_t> bitPositions) + : BitTestMatchExpression(BITS_ANY_SET, path, bitPositions) {} + + BitsAnySetMatchExpression(StringData path, uint64_t bitMask) + : BitTestMatchExpression(BITS_ANY_SET, path, bitMask) {} + + BitsAnySetMatchExpression(StringData path, const char* bitMaskBinary, uint32_t bitMaskLen) + : BitTestMatchExpression(BITS_ANY_SET, path, bitMaskBinary, bitMaskLen) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression = - stdx::make_unique<BitsAnySetMatchExpression>(); - initClone(bitTestMatchExpression.get()); + stdx::make_unique<BitsAnySetMatchExpression>(path(), getBitPositions()); + if (getTag()) { + bitTestMatchExpression->setTag(getTag()->clone()); + } return std::move(bitTestMatchExpression); } }; class BitsAnyClearMatchExpression : public BitTestMatchExpression { public: - BitsAnyClearMatchExpression() : BitTestMatchExpression(BITS_ANY_CLEAR) {} + BitsAnyClearMatchExpression(StringData path, std::vector<uint32_t> bitPositions) + : BitTestMatchExpression(BITS_ANY_CLEAR, path, bitPositions) {} + + BitsAnyClearMatchExpression(StringData path, uint64_t bitMask) + : BitTestMatchExpression(BITS_ANY_CLEAR, path, bitMask) {} + + BitsAnyClearMatchExpression(StringData path, const char* bitMaskBinary, uint32_t bitMaskLen) + : BitTestMatchExpression(BITS_ANY_CLEAR, path, bitMaskBinary, bitMaskLen) {} + virtual std::unique_ptr<MatchExpression> shallowClone() const { std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression = - stdx::make_unique<BitsAnyClearMatchExpression>(); - initClone(bitTestMatchExpression.get()); + stdx::make_unique<BitsAnyClearMatchExpression>(path(), getBitPositions()); + if (getTag()) { + bitTestMatchExpression->setTag(getTag()->clone()); + } return std::move(bitTestMatchExpression); } }; diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp index ca527fd846b..dde4439d517 100644 --- a/src/mongo/db/matcher/expression_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_leaf_test.cpp @@ -43,21 +43,23 @@ namespace mongo { using std::string; TEST(ComparisonMatchExpression, ComparisonMatchExpressionsWithUnequalCollatorsAreUnequal) { + BSONObj operand = BSON("a" << 5); CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kReverseString); - EqualityMatchExpression eq1; + EqualityMatchExpression eq1("a", operand["a"]); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kAlwaysEqual); - EqualityMatchExpression eq2; + EqualityMatchExpression eq2("a", operand["a"]); eq2.setCollator(&collator2); ASSERT(!eq1.equivalent(&eq2)); } TEST(ComparisonMatchExpression, ComparisonMatchExpressionsWithEqualCollatorsAreEqual) { + BSONObj operand = BSON("a" << 5); CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kAlwaysEqual); - EqualityMatchExpression eq1; + EqualityMatchExpression eq1("a", operand["a"]); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kAlwaysEqual); - EqualityMatchExpression eq2; + EqualityMatchExpression eq2("a", operand["a"]); eq2.setCollator(&collator2); ASSERT(eq1.equivalent(&eq2)); } @@ -65,8 +67,7 @@ TEST(ComparisonMatchExpression, ComparisonMatchExpressionsWithEqualCollatorsAreE TEST(ComparisonMatchExpression, StringMatchingWithNullCollatorUsesBinaryComparison) { BSONObj operand = BSON("a" << "string"); - EqualityMatchExpression eq; - ASSERT(eq.init("a", operand["a"]).isOK()); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(!eq.matchesBSON(BSON("a" << "string2"), NULL)); @@ -76,9 +77,8 @@ TEST(ComparisonMatchExpression, StringMatchingRespectsCollation) { BSONObj operand = BSON("a" << "string"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); - EqualityMatchExpression eq; + EqualityMatchExpression eq("a", operand["a"]); eq.setCollator(&collator); - ASSERT(eq.init("a", operand["a"]).isOK()); ASSERT(eq.matchesBSON(BSON("a" << "string2"), NULL)); @@ -89,8 +89,7 @@ TEST(EqOp, MatchesElement) { BSONObj match = BSON("a" << 5.0); BSONObj notMatch = BSON("a" << 6); - EqualityMatchExpression eq; - eq.init("", operand["a"]).transitional_ignore(); + EqualityMatchExpression eq("", operand["a"]); ASSERT(eq.matchesSingleElement(match.firstElement())); ASSERT(!eq.matchesSingleElement(notMatch.firstElement())); @@ -99,30 +98,26 @@ TEST(EqOp, MatchesElement) { DEATH_TEST(EqOp, InvalidEooOperand, "Invariant failure _rhs") { BSONObj operand; - EqualityMatchExpression eq; - eq.init("", operand.firstElement()).ignore(); + EqualityMatchExpression eq("", operand.firstElement()); } TEST(EqOp, MatchesScalar) { BSONObj operand = BSON("a" << 5); - EqualityMatchExpression eq; - eq.init("a", operand["a"]).transitional_ignore(); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSON("a" << 5.0), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL)); } TEST(EqOp, MatchesArrayValue) { BSONObj operand = BSON("a" << 5); - EqualityMatchExpression eq; - eq.init("a", operand["a"]).transitional_ignore(); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(5.0 << 6)), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL)); } TEST(EqOp, MatchesReferencedObjectValue) { BSONObj operand = BSON("a.b" << 5); - EqualityMatchExpression eq; - eq.init("a.b", operand["a.b"]).transitional_ignore(); + EqualityMatchExpression eq("a.b", operand["a.b"]); ASSERT(eq.matchesBSON(BSON("a" << BSON("b" << 5)), NULL)); ASSERT(eq.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(5))), NULL)); ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 5))), NULL)); @@ -130,16 +125,14 @@ TEST(EqOp, MatchesReferencedObjectValue) { TEST(EqOp, MatchesReferencedArrayValue) { BSONObj operand = BSON("a.0" << 5); - EqualityMatchExpression eq; - eq.init("a.0", operand["a.0"]).transitional_ignore(); + EqualityMatchExpression eq("a.0", operand["a.0"]); ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(5))), NULL)); } TEST(EqOp, MatchesNull) { BSONObj operand = BSON("a" << BSONNULL); - EqualityMatchExpression eq; - eq.init("a", operand["a"]).transitional_ignore(); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSONObj(), NULL)); ASSERT(eq.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL)); @@ -151,8 +144,7 @@ TEST(EqOp, MatchesNull) { // not necessarily how it should work ideally. TEST(EqOp, MatchesNestedNull) { BSONObj operand = BSON("a.b" << BSONNULL); - EqualityMatchExpression eq; - eq.init("a.b", operand["a.b"]).transitional_ignore(); + EqualityMatchExpression eq("a.b", operand["a.b"]); // null matches any empty object that is on a subpath of a.b ASSERT(eq.matchesBSON(BSONObj(), NULL)); ASSERT(eq.matchesBSON(BSON("a" << BSONObj()), NULL)); @@ -171,8 +163,7 @@ TEST(EqOp, MatchesNestedNull) { TEST(EqOp, MatchesMinKey) { BSONObj operand = BSON("a" << MinKey); - EqualityMatchExpression eq; - eq.init("a", operand["a"]).transitional_ignore(); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL)); @@ -181,8 +172,7 @@ TEST(EqOp, MatchesMinKey) { TEST(EqOp, MatchesMaxKey) { BSONObj operand = BSON("a" << MaxKey); - EqualityMatchExpression eq; - ASSERT(eq.init("a", operand["a"]).isOK()); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << 4), NULL)); @@ -190,8 +180,7 @@ TEST(EqOp, MatchesMaxKey) { TEST(EqOp, MatchesFullArray) { BSONObj operand = BSON("a" << BSON_ARRAY(1 << 2)); - EqualityMatchExpression eq; - ASSERT(eq.init("a", operand["a"]).isOK()); + EqualityMatchExpression eq("a", operand["a"]); ASSERT(eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3)), NULL)); ASSERT(!eq.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL)); @@ -200,16 +189,14 @@ TEST(EqOp, MatchesFullArray) { TEST(EqOp, MatchesThroughNestedArray) { BSONObj operand = BSON("a.b.c.d" << 3); - EqualityMatchExpression eq; - eq.init("a.b.c.d", operand["a.b.c.d"]).transitional_ignore(); + EqualityMatchExpression eq("a.b.c.d", operand["a.b.c.d"]); BSONObj obj = fromjson("{a:{b:[{c:[{d:1},{d:2}]},{c:[{d:3}]}]}}"); ASSERT(eq.matchesBSON(obj, NULL)); } TEST(EqOp, ElemMatchKey) { BSONObj operand = BSON("a" << 5); - EqualityMatchExpression eq; - ASSERT(eq.init("a", operand["a"]).isOK()); + EqualityMatchExpression eq("a", operand["a"]); MatchDetails details; details.requestElemMatchKey(); ASSERT(!eq.matchesBSON(BSON("a" << 4), &details)); @@ -227,8 +214,7 @@ TEST(EqOp, ElemMatchKey) { TEST(EqOp, ElemMatchKeyWithImplicitAndExplicitTraversal) { BSONObj operand = BSON("a.0.b" << 3); BSONElement operandFirstElt = operand.firstElement(); - EqualityMatchExpression eq; - ASSERT(eq.init(operandFirstElt.fieldName(), operandFirstElt).isOK()); + EqualityMatchExpression eq(operandFirstElt.fieldName(), operandFirstElt); MatchDetails details; details.requestElemMatchKey(); BSONObj obj = fromjson("{a: [{b: [2, 3]}, {b: [4, 5]}]}"); @@ -238,71 +224,16 @@ TEST(EqOp, ElemMatchKeyWithImplicitAndExplicitTraversal) { } TEST(EqOp, Equality1) { - EqualityMatchExpression eq1; - EqualityMatchExpression eq2; - EqualityMatchExpression eq3; - BSONObj operand = BSON("a" << 5 << "b" << 5 << "c" << 4); - - eq1.init("a", operand["a"]).transitional_ignore(); - eq2.init("a", operand["b"]).transitional_ignore(); - eq3.init("c", operand["c"]).transitional_ignore(); + EqualityMatchExpression eq1("a", operand["a"]); + EqualityMatchExpression eq2("a", operand["b"]); + EqualityMatchExpression eq3("c", operand["c"]); ASSERT(eq1.equivalent(&eq1)); ASSERT(eq1.equivalent(&eq2)); ASSERT(!eq1.equivalent(&eq3)); } -/** - TEST( EqOp, MatchesIndexKeyScalar ) { - BSONObj operand = BSON( "a" << 6 ); - EqualityMatchExpression eq; - ASSERT( eq.init( "a", operand[ "a" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 6 ) ), indexSpec ) ); - } - - TEST( EqOp, MatchesIndexKeyMissing ) { - BSONObj operand = BSON( "a" << 6 ); - EqualityMatchExpression eq; - ASSERT( eq.init( "a", operand[ "a" ] ).isOK() ); - IndexSpec indexSpec( BSON( "b" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - eq.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - eq.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) ); - } - - TEST( EqOp, MatchesIndexKeyArray ) { - BSONObj operand = BSON( "a" << BSON_ARRAY( 4 << 5 ) ); - ComparisonMatchExpression eq - ASSERT( eq.init( "a", operand[ "a" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - eq.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - } - - TEST( EqOp, MatchesIndexKeyArrayValue ) { - BSONObj operand = BSON( "a" << 6 ); - ComparisonMatchExpression eq - ASSERT( eq.init( "a", operand[ "a" ] ).isOK() ); - IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - eq.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - eq.matchesIndexKey( BSON( "" << "dummygeohash" << - "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) ); - } -*/ TEST(LtOp, MatchesElement) { BSONObj operand = BSON("$lt" << 5); BSONObj match = BSON("a" << 4.5); @@ -310,8 +241,7 @@ TEST(LtOp, MatchesElement) { BSONObj notMatchEqual = BSON("a" << 5); BSONObj notMatchWrongType = BSON("a" << "foo"); - LTMatchExpression lt; - ASSERT(lt.init("", operand["$lt"]).isOK()); + LTMatchExpression lt("", operand["$lt"]); ASSERT(lt.matchesSingleElement(match.firstElement())); ASSERT(!lt.matchesSingleElement(notMatch.firstElement())); ASSERT(!lt.matchesSingleElement(notMatchEqual.firstElement())); @@ -320,38 +250,33 @@ TEST(LtOp, MatchesElement) { DEATH_TEST(LtOp, InvalidEooOperand, "Invariant failure _rhs") { BSONObj operand; - LTMatchExpression lt; - lt.init("", operand.firstElement()).ignore(); + LTMatchExpression lt("", operand.firstElement()); } TEST(LtOp, MatchesScalar) { BSONObj operand = BSON("$lt" << 5); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["$lt"]).isOK()); + LTMatchExpression lt("a", operand["$lt"]); ASSERT(lt.matchesBSON(BSON("a" << 4.5), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << 6), NULL)); } TEST(LtOp, MatchesScalarEmptyKey) { BSONObj operand = BSON("$lt" << 5); - LTMatchExpression lt; - ASSERT(lt.init("", operand["$lt"]).isOK()); + LTMatchExpression lt("", operand["$lt"]); ASSERT(lt.matchesBSON(BSON("" << 4.5), NULL)); ASSERT(!lt.matchesBSON(BSON("" << 6), NULL)); } TEST(LtOp, MatchesArrayValue) { BSONObj operand = BSON("$lt" << 5); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["$lt"]).isOK()); + LTMatchExpression lt("a", operand["$lt"]); ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(6 << 4.5)), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL)); } TEST(LtOp, MatchesWholeArray) { BSONObj operand = BSON("$lt" << BSON_ARRAY(5)); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["$lt"]).isOK()); + LTMatchExpression lt("a", operand["$lt"]); ASSERT(lt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); @@ -363,8 +288,7 @@ TEST(LtOp, MatchesWholeArray) { TEST(LtOp, MatchesNull) { BSONObj operand = BSON("$lt" << BSONNULL); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["$lt"]).isOK()); + LTMatchExpression lt("a", operand["$lt"]); ASSERT(!lt.matchesBSON(BSONObj(), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL)); @@ -374,8 +298,7 @@ TEST(LtOp, MatchesNull) { TEST(LtOp, MatchesDotNotationNull) { BSONObj operand = BSON("$lt" << BSONNULL); - LTMatchExpression lt; - ASSERT(lt.init("a.b", operand["$lt"]).isOK()); + LTMatchExpression lt("a.b", operand["$lt"]); ASSERT(!lt.matchesBSON(BSONObj(), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL)); @@ -388,8 +311,7 @@ TEST(LtOp, MatchesDotNotationNull) { TEST(LtOp, MatchesMinKey) { BSONObj operand = BSON("a" << MinKey); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["a"]).isOK()); + LTMatchExpression lt("a", operand["a"]); ASSERT(!lt.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!lt.matchesBSON(BSON("a" << 4), NULL)); @@ -397,8 +319,7 @@ TEST(LtOp, MatchesMinKey) { TEST(LtOp, MatchesMaxKey) { BSONObj operand = BSON("a" << MaxKey); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["a"]).isOK()); + LTMatchExpression lt("a", operand["a"]); ASSERT(!lt.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(lt.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(lt.matchesBSON(BSON("a" << 4), NULL)); @@ -406,8 +327,7 @@ TEST(LtOp, MatchesMaxKey) { TEST(LtOp, ElemMatchKey) { BSONObj operand = BSON("$lt" << 5); - LTMatchExpression lt; - ASSERT(lt.init("a", operand["$lt"]).isOK()); + LTMatchExpression lt("a", operand["$lt"]); MatchDetails details; details.requestElemMatchKey(); ASSERT(!lt.matchesBSON(BSON("a" << 6), &details)); @@ -419,56 +339,6 @@ TEST(LtOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } -/** - TEST( LtOp, MatchesIndexKeyScalar ) { - BSONObj operand = BSON( "$lt" << 6 ); - LtOp lt; - ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) ); - } - - TEST( LtOp, MatchesIndexKeyMissing ) { - BSONObj operand = BSON( "$lt" << 6 ); - LtOp lt; - ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "b" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) ); - } - - TEST( LtOp, MatchesIndexKeyArray ) { - BSONObj operand = BSON( "$lt" << BSON_ARRAY( 4 << 5 ) ); - LtOp lt; - ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lt.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - } - - TEST( LtOp, MatchesIndexKeyArrayValue ) { - BSONObj operand = BSON( "$lt" << 6 ); - LtOp lt; - ASSERT( lt.init( "a", operand[ "$lt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lt.matchesIndexKey( BSON( "" << "dummygeohash" << - "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) ); - } -*/ TEST(LteOp, MatchesElement) { BSONObj operand = BSON("$lte" << 5); BSONObj match = BSON("a" << 4.5); @@ -476,8 +346,7 @@ TEST(LteOp, MatchesElement) { BSONObj notMatch = BSON("a" << 6); BSONObj notMatchWrongType = BSON("a" << "foo"); - LTEMatchExpression lte; - ASSERT(lte.init("", operand["$lte"]).isOK()); + LTEMatchExpression lte("", operand["$lte"]); ASSERT(lte.matchesSingleElement(match.firstElement())); ASSERT(lte.matchesSingleElement(equalMatch.firstElement())); ASSERT(!lte.matchesSingleElement(notMatch.firstElement())); @@ -486,30 +355,26 @@ TEST(LteOp, MatchesElement) { DEATH_TEST(LteOp, InvalidEooOperand, "Invariant failure _rhs") { BSONObj operand; - LTEMatchExpression lte; - lte.init("", operand.firstElement()).ignore(); + LTEMatchExpression lte("", operand.firstElement()); } TEST(LteOp, MatchesScalar) { BSONObj operand = BSON("$lte" << 5); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["$lte"]).isOK()); + LTEMatchExpression lte("a", operand["$lte"]); ASSERT(lte.matchesBSON(BSON("a" << 4.5), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << 6), NULL)); } TEST(LteOp, MatchesArrayValue) { BSONObj operand = BSON("$lte" << 5); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["$lte"]).isOK()); + LTEMatchExpression lte("a", operand["$lte"]); ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(6 << 4.5)), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(6 << 7)), NULL)); } TEST(LteOp, MatchesWholeArray) { BSONObj operand = BSON("$lte" << BSON_ARRAY(5)); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["$lte"]).isOK()); + LTEMatchExpression lte("a", operand["$lte"]); ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); ASSERT(lte.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); @@ -521,8 +386,7 @@ TEST(LteOp, MatchesWholeArray) { TEST(LteOp, MatchesNull) { BSONObj operand = BSON("$lte" << BSONNULL); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["$lte"]).isOK()); + LTEMatchExpression lte("a", operand["$lte"]); ASSERT(lte.matchesBSON(BSONObj(), NULL)); ASSERT(lte.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << 4), NULL)); @@ -532,8 +396,7 @@ TEST(LteOp, MatchesNull) { TEST(LteOp, MatchesDotNotationNull) { BSONObj operand = BSON("$lte" << BSONNULL); - LTEMatchExpression lte; - ASSERT(lte.init("a.b", operand["$lte"]).isOK()); + LTEMatchExpression lte("a.b", operand["$lte"]); ASSERT(lte.matchesBSON(BSONObj(), NULL)); ASSERT(lte.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(lte.matchesBSON(BSON("a" << 4), NULL)); @@ -546,8 +409,7 @@ TEST(LteOp, MatchesDotNotationNull) { TEST(LteOp, MatchesMinKey) { BSONObj operand = BSON("a" << MinKey); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["a"]).isOK()); + LTEMatchExpression lte("a", operand["a"]); ASSERT(lte.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!lte.matchesBSON(BSON("a" << 4), NULL)); @@ -555,8 +417,7 @@ TEST(LteOp, MatchesMinKey) { TEST(LteOp, MatchesMaxKey) { BSONObj operand = BSON("a" << MaxKey); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["a"]).isOK()); + LTEMatchExpression lte("a", operand["a"]); ASSERT(lte.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(lte.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(lte.matchesBSON(BSON("a" << 4), NULL)); @@ -565,8 +426,7 @@ TEST(LteOp, MatchesMaxKey) { TEST(LteOp, ElemMatchKey) { BSONObj operand = BSON("$lte" << 5); - LTEMatchExpression lte; - ASSERT(lte.init("a", operand["$lte"]).isOK()); + LTEMatchExpression lte("a", operand["$lte"]); MatchDetails details; details.requestElemMatchKey(); ASSERT(!lte.matchesBSON(BSON("a" << 6), &details)); @@ -578,97 +438,28 @@ TEST(LteOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } -/** - TEST( LteOp, MatchesIndexKeyScalar ) { - BSONObj operand = BSON( "$lte" << 6 ); - LteOp lte; - ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lte.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 5 ) ), indexSpec ) ); - } - - TEST( LteOp, MatchesIndexKeyMissing ) { - BSONObj operand = BSON( "$lte" << 6 ); - LteOp lte; - ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() ); - IndexSpec indexSpec( BSON( "b" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lte.matchesIndexKey( BSON( "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lte.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lte.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) ); - } - - TEST( LteOp, MatchesIndexKeyArray ) { - BSONObj operand = BSON( "$lte" << BSON_ARRAY( 4 << 5 ) ); - LteOp lte; - ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - lte.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - } - - TEST( LteOp, MatchesIndexKeyArrayValue ) { - BSONObj operand = BSON( "$lte" << 6 ); - LteOp lte; - ASSERT( lte.init( "a", operand[ "$lte" ] ).isOK() ); - IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - lte.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - lte.matchesIndexKey( BSON( "" << "dummygeohash" << - "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) ); - } - - TEST( GtOp, MatchesElement ) { - BSONObj operand = BSON( "$gt" << 5 ); - BSONObj match = BSON( "a" << 5.5 ); - BSONObj notMatch = BSON( "a" << 4 ); - BSONObj notMatchEqual = BSON( "a" << 5 ); - BSONObj notMatchWrongType = BSON( "a" << "foo" ); - GtOp gt; - ASSERT( gt.init( "", operand[ "$gt" ] ).isOK() ); - ASSERT( gt.matchesSingleElement( match.firstElement() ) ); - ASSERT( !gt.matchesSingleElement( notMatch.firstElement() ) ); - ASSERT( !gt.matchesSingleElement( notMatchEqual.firstElement() ) ); - ASSERT( !gt.matchesSingleElement( notMatchWrongType.firstElement() ) ); - } -*/ - DEATH_TEST(GtOp, InvalidEooOperand, "Invariant failure _rhs") { BSONObj operand; - GTMatchExpression gt; - gt.init("", operand.firstElement()).ignore(); + GTMatchExpression gt("", operand.firstElement()); } TEST(GtOp, MatchesScalar) { BSONObj operand = BSON("$gt" << 5); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["$gt"]).isOK()); + GTMatchExpression gt("a", operand["$gt"]); ASSERT(gt.matchesBSON(BSON("a" << 5.5), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL)); } TEST(GtOp, MatchesArrayValue) { BSONObj operand = BSON("$gt" << 5); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["$gt"]).isOK()); + GTMatchExpression gt("a", operand["$gt"]); ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(3 << 5.5)), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(2 << 4)), NULL)); } TEST(GtOp, MatchesWholeArray) { BSONObj operand = BSON("$gt" << BSON_ARRAY(5)); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["$gt"]).isOK()); + GTMatchExpression gt("a", operand["$gt"]); ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL)); ASSERT(gt.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); @@ -682,8 +473,7 @@ TEST(GtOp, MatchesWholeArray) { TEST(GtOp, MatchesNull) { BSONObj operand = BSON("$gt" << BSONNULL); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["$gt"]).isOK()); + GTMatchExpression gt("a", operand["$gt"]); ASSERT(!gt.matchesBSON(BSONObj(), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL)); @@ -693,8 +483,7 @@ TEST(GtOp, MatchesNull) { TEST(GtOp, MatchesDotNotationNull) { BSONObj operand = BSON("$gt" << BSONNULL); - GTMatchExpression gt; - ASSERT(gt.init("a.b", operand["$gt"]).isOK()); + GTMatchExpression gt("a.b", operand["$gt"]); ASSERT(!gt.matchesBSON(BSONObj(), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL)); @@ -707,8 +496,7 @@ TEST(GtOp, MatchesDotNotationNull) { TEST(GtOp, MatchesMinKey) { BSONObj operand = BSON("a" << MinKey); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["a"]).isOK()); + GTMatchExpression gt("a", operand["a"]); ASSERT(!gt.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(gt.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(gt.matchesBSON(BSON("a" << 4), NULL)); @@ -716,8 +504,7 @@ TEST(GtOp, MatchesMinKey) { TEST(GtOp, MatchesMaxKey) { BSONObj operand = BSON("a" << MaxKey); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["a"]).isOK()); + GTMatchExpression gt("a", operand["a"]); ASSERT(!gt.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!gt.matchesBSON(BSON("a" << 4), NULL)); @@ -725,8 +512,7 @@ TEST(GtOp, MatchesMaxKey) { TEST(GtOp, ElemMatchKey) { BSONObj operand = BSON("$gt" << 5); - GTMatchExpression gt; - ASSERT(gt.init("a", operand["$gt"]).isOK()); + GTMatchExpression gt("a", operand["$gt"]); MatchDetails details; details.requestElemMatchKey(); ASSERT(!gt.matchesBSON(BSON("a" << 4), &details)); @@ -738,57 +524,6 @@ TEST(GtOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } -/** - TEST( GtOp, MatchesIndexKeyScalar ) { - BSONObj operand = BSON( "$gt" << 6 ); - GtOp gt; - ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - gt.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 9 ) ), indexSpec ) ); - } - - TEST( GtOp, MatchesIndexKeyMissing ) { - BSONObj operand = BSON( "$gt" << 6 ); - GtOp gt; - ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "b" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - gt.matchesIndexKey( BSON( "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - gt.matchesIndexKey( BSON( "" << 4 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - gt.matchesIndexKey( BSON( "" << BSON_ARRAY( 8 << 6 ) ), indexSpec ) ); - } - - TEST( GtOp, MatchesIndexKeyArray ) { - BSONObj operand = BSON( "$gt" << BSON_ARRAY( 4 << 5 ) ); - GtOp gt; - ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - gt.matchesIndexKey( BSON( "" << 8 ), indexSpec ) ); - } - - TEST( GtOp, MatchesIndexKeyArrayValue ) { - BSONObj operand = BSON( "$gt" << 6 ); - GtOp gt; - ASSERT( gt.init( "a", operand[ "$gt" ] ).isOK() ); - IndexSpec indexSpec( BSON( "loc" << "mockarrayvalue" << "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 7 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - gt.matchesIndexKey( BSON( "" << "dummygeohash" << "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - gt.matchesIndexKey( BSON( "" << "dummygeohash" << - "" << BSON_ARRAY( 8 << 6 << 4 ) ), indexSpec ) ); - } -*/ - TEST(GteOp, MatchesElement) { BSONObj operand = BSON("$gte" << 5); BSONObj match = BSON("a" << 5.5); @@ -796,8 +531,7 @@ TEST(GteOp, MatchesElement) { BSONObj notMatch = BSON("a" << 4); BSONObj notMatchWrongType = BSON("a" << "foo"); - GTEMatchExpression gte; - ASSERT(gte.init("", operand["$gte"]).isOK()); + GTEMatchExpression gte("", operand["$gte"]); ASSERT(gte.matchesSingleElement(match.firstElement())); ASSERT(gte.matchesSingleElement(equalMatch.firstElement())); ASSERT(!gte.matchesSingleElement(notMatch.firstElement())); @@ -806,30 +540,26 @@ TEST(GteOp, MatchesElement) { DEATH_TEST(GteOp, InvalidEooOperand, "Invariant failure _rhs") { BSONObj operand; - GTEMatchExpression gte; - gte.init("", operand.firstElement()).ignore(); + GTEMatchExpression gte("", operand.firstElement()); } TEST(GteOp, MatchesScalar) { BSONObj operand = BSON("$gte" << 5); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["$gte"]).isOK()); + GTEMatchExpression gte("a", operand["$gte"]); ASSERT(gte.matchesBSON(BSON("a" << 5.5), NULL)); ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL)); } TEST(GteOp, MatchesArrayValue) { BSONObj operand = BSON("$gte" << 5); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["$gte"]).isOK()); + GTEMatchExpression gte("a", operand["$gte"]); ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL)); ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)), NULL)); } TEST(GteOp, MatchesWholeArray) { BSONObj operand = BSON("$gte" << BSON_ARRAY(5)); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["$gte"]).isOK()); + GTEMatchExpression gte("a", operand["$gte"]); ASSERT(!gte.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(5)), NULL)); ASSERT(gte.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); @@ -842,8 +572,7 @@ TEST(GteOp, MatchesWholeArray) { TEST(GteOp, MatchesNull) { BSONObj operand = BSON("$gte" << BSONNULL); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["$gte"]).isOK()); + GTEMatchExpression gte("a", operand["$gte"]); ASSERT(gte.matchesBSON(BSONObj(), NULL)); ASSERT(gte.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL)); @@ -853,8 +582,7 @@ TEST(GteOp, MatchesNull) { TEST(GteOp, MatchesDotNotationNull) { BSONObj operand = BSON("$gte" << BSONNULL); - GTEMatchExpression gte; - ASSERT(gte.init("a.b", operand["$gte"]).isOK()); + GTEMatchExpression gte("a.b", operand["$gte"]); ASSERT(gte.matchesBSON(BSONObj(), NULL)); ASSERT(gte.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(gte.matchesBSON(BSON("a" << 4), NULL)); @@ -867,8 +595,7 @@ TEST(GteOp, MatchesDotNotationNull) { TEST(GteOp, MatchesMinKey) { BSONObj operand = BSON("a" << MinKey); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["a"]).isOK()); + GTEMatchExpression gte("a", operand["a"]); ASSERT(gte.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(gte.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(gte.matchesBSON(BSON("a" << 4), NULL)); @@ -876,8 +603,7 @@ TEST(GteOp, MatchesMinKey) { TEST(GteOp, MatchesMaxKey) { BSONObj operand = BSON("a" << MaxKey); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["a"]).isOK()); + GTEMatchExpression gte("a", operand["a"]); ASSERT(gte.matchesBSON(BSON("a" << MaxKey), NULL)); ASSERT(!gte.matchesBSON(BSON("a" << MinKey), NULL)); ASSERT(!gte.matchesBSON(BSON("a" << 4), NULL)); @@ -885,8 +611,7 @@ TEST(GteOp, MatchesMaxKey) { TEST(GteOp, ElemMatchKey) { BSONObj operand = BSON("$gte" << 5); - GTEMatchExpression gte; - ASSERT(gte.init("a", operand["$gte"]).isOK()); + GTEMatchExpression gte("a", operand["$gte"]); MatchDetails details; details.requestElemMatchKey(); ASSERT(!gte.matchesBSON(BSON("a" << 4), &details)); @@ -903,16 +628,16 @@ TEST(RegexMatchExpression, MatchesElementExact) { << "b"); BSONObj notMatch = BSON("a" << "c"); - RegexMatchExpression regex; - ASSERT(regex.init("", "b", "").isOK()); + RegexMatchExpression regex("", "b", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } TEST(RegexMatchExpression, TooLargePattern) { string tooLargePattern(50 * 1000, 'z'); - RegexMatchExpression regex; - ASSERT(!regex.init("a", tooLargePattern, "").isOK()); + ASSERT_THROWS_CODE(RegexMatchExpression regex("a", tooLargePattern, ""), + AssertionException, + ErrorCodes::BadValue); } TEST(RegexMatchExpression, MatchesElementSimplePrefix) { @@ -920,8 +645,7 @@ TEST(RegexMatchExpression, MatchesElementSimplePrefix) { << "abc"); BSONObj notMatch = BSON("x" << "adz"); - RegexMatchExpression regex; - ASSERT(regex.init("", "^ab", "").isOK()); + RegexMatchExpression regex("", "^ab", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -931,8 +655,7 @@ TEST(RegexMatchExpression, MatchesElementCaseSensitive) { << "abc"); BSONObj notMatch = BSON("x" << "ABC"); - RegexMatchExpression regex; - ASSERT(regex.init("", "abc", "").isOK()); + RegexMatchExpression regex("", "abc", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -944,8 +667,7 @@ TEST(RegexMatchExpression, MatchesElementCaseInsensitive) { << "ABC"); BSONObj notMatch = BSON("x" << "abz"); - RegexMatchExpression regex; - ASSERT(regex.init("", "abc", "i").isOK()); + RegexMatchExpression regex("", "abc", "i"); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(regex.matchesSingleElement(matchUppercase.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); @@ -956,8 +678,7 @@ TEST(RegexMatchExpression, MatchesElementMultilineOff) { << "az"); BSONObj notMatch = BSON("x" << "\naz"); - RegexMatchExpression regex; - ASSERT(regex.init("", "^a", "").isOK()); + RegexMatchExpression regex("", "^a", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -969,8 +690,7 @@ TEST(RegexMatchExpression, MatchesElementMultilineOn) { << "\naz"); BSONObj notMatch = BSON("x" << "\n\n"); - RegexMatchExpression regex; - ASSERT(regex.init("", "^a", "m").isOK()); + RegexMatchExpression regex("", "^a", "m"); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(regex.matchesSingleElement(matchMultiline.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); @@ -981,8 +701,7 @@ TEST(RegexMatchExpression, MatchesElementExtendedOff) { << "a b"); BSONObj notMatch = BSON("x" << "ab"); - RegexMatchExpression regex; - ASSERT(regex.init("", "a b", "").isOK()); + RegexMatchExpression regex("", "a b", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -992,8 +711,7 @@ TEST(RegexMatchExpression, MatchesElementExtendedOn) { << "ab"); BSONObj notMatch = BSON("x" << "a b"); - RegexMatchExpression regex; - ASSERT(regex.init("", "a b", "x").isOK()); + RegexMatchExpression regex("", "a b", "x"); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -1003,8 +721,7 @@ TEST(RegexMatchExpression, MatchesElementDotAllOff) { << "a b"); BSONObj notMatch = BSON("x" << "a\nb"); - RegexMatchExpression regex; - ASSERT(regex.init("", "a.b", "").isOK()); + RegexMatchExpression regex("", "a.b", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -1016,8 +733,7 @@ TEST(RegexMatchExpression, MatchesElementDotAllOn) { << "a\nb"); BSONObj notMatch = BSON("x" << "ab"); - RegexMatchExpression regex; - ASSERT(regex.init("", "a.b", "s").isOK()); + RegexMatchExpression regex("", "a.b", "s"); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(regex.matchesSingleElement(matchDotAll.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); @@ -1026,8 +742,7 @@ TEST(RegexMatchExpression, MatchesElementDotAllOn) { TEST(RegexMatchExpression, MatchesElementMultipleFlags) { BSONObj matchMultilineDotAll = BSON("x" << "\na\nb"); - RegexMatchExpression regex; - ASSERT(regex.init("", "^a.b", "ms").isOK()); + RegexMatchExpression regex("", "^a.b", "ms"); ASSERT(regex.matchesSingleElement(matchMultilineDotAll.firstElement())); } @@ -1035,8 +750,7 @@ TEST(RegexMatchExpression, MatchesElementRegexType) { BSONObj match = BSONObjBuilder().appendRegex("x", "yz", "i").obj(); BSONObj notMatchPattern = BSONObjBuilder().appendRegex("x", "r", "i").obj(); BSONObj notMatchFlags = BSONObjBuilder().appendRegex("x", "yz", "s").obj(); - RegexMatchExpression regex; - ASSERT(regex.init("", "yz", "i").isOK()); + RegexMatchExpression regex("", "yz", "i"); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatchPattern.firstElement())); ASSERT(!regex.matchesSingleElement(notMatchFlags.firstElement())); @@ -1045,8 +759,7 @@ TEST(RegexMatchExpression, MatchesElementRegexType) { TEST(RegexMatchExpression, MatchesElementSymbolType) { BSONObj match = BSONObjBuilder().appendSymbol("x", "yz").obj(); BSONObj notMatch = BSONObjBuilder().appendSymbol("x", "gg").obj(); - RegexMatchExpression regex; - ASSERT(regex.init("", "yz", "").isOK()); + RegexMatchExpression regex("", "yz", ""); ASSERT(regex.matchesSingleElement(match.firstElement())); ASSERT(!regex.matchesSingleElement(notMatch.firstElement())); } @@ -1054,8 +767,7 @@ TEST(RegexMatchExpression, MatchesElementSymbolType) { TEST(RegexMatchExpression, MatchesElementWrongType) { BSONObj notMatchInt = BSON("x" << 1); BSONObj notMatchBool = BSON("x" << true); - RegexMatchExpression regex; - ASSERT(regex.init("", "1", "").isOK()); + RegexMatchExpression regex("", "1", ""); ASSERT(!regex.matchesSingleElement(notMatchInt.firstElement())); ASSERT(!regex.matchesSingleElement(notMatchBool.firstElement())); } @@ -1063,14 +775,12 @@ TEST(RegexMatchExpression, MatchesElementWrongType) { TEST(RegexMatchExpression, MatchesElementUtf8) { BSONObj multiByteCharacter = BSON("x" << "\xc2\xa5"); - RegexMatchExpression regex; - ASSERT(regex.init("", "^.$", "").isOK()); + RegexMatchExpression regex("", "^.$", ""); ASSERT(regex.matchesSingleElement(multiByteCharacter.firstElement())); } TEST(RegexMatchExpression, MatchesScalar) { - RegexMatchExpression regex; - ASSERT(regex.init("a", "b", "").isOK()); + RegexMatchExpression regex("a", "b", ""); ASSERT(regex.matchesBSON(BSON("a" << "b"), NULL)); @@ -1080,8 +790,7 @@ TEST(RegexMatchExpression, MatchesScalar) { } TEST(RegexMatchExpression, MatchesArrayValue) { - RegexMatchExpression regex; - ASSERT(regex.init("a", "b", "").isOK()); + RegexMatchExpression regex("a", "b", ""); ASSERT(regex.matchesBSON(BSON("a" << BSON_ARRAY("c" << "b")), NULL)); @@ -1091,15 +800,13 @@ TEST(RegexMatchExpression, MatchesArrayValue) { } TEST(RegexMatchExpression, MatchesNull) { - RegexMatchExpression regex; - ASSERT(regex.init("a", "b", "").isOK()); + RegexMatchExpression regex("a", "b", ""); ASSERT(!regex.matchesBSON(BSONObj(), NULL)); ASSERT(!regex.matchesBSON(BSON("a" << BSONNULL), NULL)); } TEST(RegexMatchExpression, ElemMatchKey) { - RegexMatchExpression regex; - ASSERT(regex.init("a", "b", "").isOK()); + RegexMatchExpression regex("a", "b", ""); MatchDetails details; details.requestElemMatchKey(); ASSERT(!regex.matchesBSON(BSON("a" @@ -1118,14 +825,10 @@ TEST(RegexMatchExpression, ElemMatchKey) { } TEST(RegexMatchExpression, Equality1) { - RegexMatchExpression r1; - RegexMatchExpression r2; - RegexMatchExpression r3; - RegexMatchExpression r4; - ASSERT(r1.init("a", "b", "").isOK()); - ASSERT(r2.init("a", "b", "x").isOK()); - ASSERT(r3.init("a", "c", "").isOK()); - ASSERT(r4.init("b", "b", "").isOK()); + RegexMatchExpression r1("a", "b", ""); + RegexMatchExpression r2("a", "b", "x"); + RegexMatchExpression r3("a", "c", ""); + RegexMatchExpression r4("b", "b", ""); ASSERT(r1.equivalent(&r1)); ASSERT(!r1.equivalent(&r2)); @@ -1134,55 +837,69 @@ TEST(RegexMatchExpression, Equality1) { } TEST(RegexMatchExpression, RegexCannotContainEmbeddedNullByte) { - RegexMatchExpression regex; { const auto embeddedNull = "a\0b"_sd; - ASSERT_NOT_OK(regex.init("path", embeddedNull, "")); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", embeddedNull, ""), + AssertionException, + ErrorCodes::BadValue); } { const auto singleNullByte = "\0"_sd; - ASSERT_NOT_OK(regex.init("path", singleNullByte, "")); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", singleNullByte, ""), + AssertionException, + ErrorCodes::BadValue); } { const auto leadingNullByte = "\0bbbb"_sd; - ASSERT_NOT_OK(regex.init("path", leadingNullByte, "")); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", leadingNullByte, ""), + AssertionException, + ErrorCodes::BadValue); } { const auto trailingNullByte = "bbbb\0"_sd; - ASSERT_NOT_OK(regex.init("path", trailingNullByte, "")); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", trailingNullByte, ""), + AssertionException, + ErrorCodes::BadValue); } } TEST(RegexMatchExpression, RegexOptionsStringCannotContainEmbeddedNullByte) { - RegexMatchExpression regex; { const auto embeddedNull = "a\0b"_sd; - ASSERT_NOT_OK(regex.init("path", "pattern", embeddedNull)); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", "pattern", embeddedNull), + AssertionException, + ErrorCodes::BadValue); } { const auto singleNullByte = "\0"_sd; - ASSERT_NOT_OK(regex.init("path", "pattern", singleNullByte)); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", "pattern", singleNullByte), + AssertionException, + ErrorCodes::BadValue); } { const auto leadingNullByte = "\0bbbb"_sd; - ASSERT_NOT_OK(regex.init("path", "pattern", leadingNullByte)); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", "pattern", leadingNullByte), + AssertionException, + ErrorCodes::BadValue); } { const auto trailingNullByte = "bbbb\0"_sd; - ASSERT_NOT_OK(regex.init("path", "pattern", trailingNullByte)); + ASSERT_THROWS_CODE(RegexMatchExpression regex("path", "pattern", trailingNullByte), + AssertionException, + ErrorCodes::BadValue); } } TEST(RegexMatchExpression, RegexCannotBeInvalid) { - RegexMatchExpression regex; const auto invalid = "["_sd; - ASSERT_NOT_OK(regex.init("path", invalid, "")); + ASSERT_THROWS_CODE( + RegexMatchExpression regex("path", invalid, ""), AssertionException, ErrorCodes::BadValue); } TEST(ModMatchExpression, MatchesElement) { @@ -1191,8 +908,7 @@ TEST(ModMatchExpression, MatchesElement) { BSONObj longLongMatch = BSON("a" << 68719476736LL); BSONObj notMatch = BSON("a" << 6); BSONObj negativeNotMatch = BSON("a" << -2); - ModMatchExpression mod; - ASSERT(mod.init("", 3, 1).isOK()); + ModMatchExpression mod("", 3, 1); ASSERT(mod.matchesSingleElement(match.firstElement())); ASSERT(mod.matchesSingleElement(largerMatch.firstElement())); ASSERT(mod.matchesSingleElement(longLongMatch.firstElement())); @@ -1201,34 +917,29 @@ TEST(ModMatchExpression, MatchesElement) { } TEST(ModMatchExpression, ZeroDivisor) { - ModMatchExpression mod; - ASSERT(!mod.init("", 0, 1).isOK()); + ASSERT_THROWS_CODE(ModMatchExpression mod("", 0, 1), AssertionException, ErrorCodes::BadValue); } TEST(ModMatchExpression, MatchesScalar) { - ModMatchExpression mod; - ASSERT(mod.init("a", 5, 2).isOK()); + ModMatchExpression mod("a", 5, 2); ASSERT(mod.matchesBSON(BSON("a" << 7.0), NULL)); ASSERT(!mod.matchesBSON(BSON("a" << 4), NULL)); } TEST(ModMatchExpression, MatchesArrayValue) { - ModMatchExpression mod; - ASSERT(mod.init("a", 5, 2).isOK()); + ModMatchExpression mod("a", 5, 2); ASSERT(mod.matchesBSON(BSON("a" << BSON_ARRAY(5 << 12LL)), NULL)); ASSERT(!mod.matchesBSON(BSON("a" << BSON_ARRAY(6 << 8)), NULL)); } TEST(ModMatchExpression, MatchesNull) { - ModMatchExpression mod; - ASSERT(mod.init("a", 5, 2).isOK()); + ModMatchExpression mod("a", 5, 2); ASSERT(!mod.matchesBSON(BSONObj(), NULL)); ASSERT(!mod.matchesBSON(BSON("a" << BSONNULL), NULL)); } TEST(ModMatchExpression, ElemMatchKey) { - ModMatchExpression mod; - ASSERT(mod.init("a", 5, 2).isOK()); + ModMatchExpression mod("a", 5, 2); MatchDetails details; details.requestElemMatchKey(); ASSERT(!mod.matchesBSON(BSON("a" << 4), &details)); @@ -1241,15 +952,10 @@ TEST(ModMatchExpression, ElemMatchKey) { } TEST(ModMatchExpression, Equality1) { - ModMatchExpression m1; - ModMatchExpression m2; - ModMatchExpression m3; - ModMatchExpression m4; - - m1.init("a", 1, 2).transitional_ignore(); - m2.init("a", 2, 2).transitional_ignore(); - m3.init("a", 1, 1).transitional_ignore(); - m4.init("b", 1, 2).transitional_ignore(); + ModMatchExpression m1("a", 1, 2); + ModMatchExpression m2("a", 2, 2); + ModMatchExpression m3("a", 1, 1); + ModMatchExpression m4("b", 1, 2); ASSERT(m1.equivalent(&m1)); ASSERT(!m1.equivalent(&m2)); @@ -1257,24 +963,11 @@ TEST(ModMatchExpression, Equality1) { ASSERT(!m1.equivalent(&m4)); } -/** - TEST( ModMatchExpression, MatchesIndexKey ) { - BSONObj operand = BSON( "$mod" << BSON_ARRAY( 2 << 1 ) ); - ModMatchExpression mod; - ASSERT( mod.init( "a", operand[ "$mod" ] ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - BSONObj indexKey = BSON( "" << 1 ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - mod.matchesIndexKey( indexKey, indexSpec ) ); - } -*/ - TEST(ExistsMatchExpression, MatchesElement) { BSONObj existsInt = BSON("a" << 5); BSONObj existsNull = BSON("a" << BSONNULL); BSONObj doesntExist = BSONObj(); - ExistsMatchExpression exists; - ASSERT(exists.init("").isOK()); + ExistsMatchExpression exists(""); ASSERT(exists.matchesSingleElement(existsInt.firstElement())); ASSERT(exists.matchesSingleElement(existsNull.firstElement())); ASSERT(!exists.matchesSingleElement(doesntExist.firstElement())); @@ -1283,29 +976,25 @@ TEST(ExistsMatchExpression, MatchesElement) { TEST(ExistsMatchExpression, MatchesElementExistsTrueValue) { BSONObj exists = BSON("a" << 5); BSONObj missing = BSONObj(); - ExistsMatchExpression existsTrueValue; - ASSERT(existsTrueValue.init("").isOK()); + ExistsMatchExpression existsTrueValue(""); ASSERT(existsTrueValue.matchesSingleElement(exists.firstElement())); ASSERT(!existsTrueValue.matchesSingleElement(missing.firstElement())); } TEST(ExistsMatchExpression, MatchesScalar) { - ExistsMatchExpression exists; - ASSERT(exists.init("a").isOK()); + ExistsMatchExpression exists("a"); ASSERT(exists.matchesBSON(BSON("a" << 1), NULL)); ASSERT(exists.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!exists.matchesBSON(BSON("b" << 1), NULL)); } TEST(ExistsMatchExpression, MatchesArray) { - ExistsMatchExpression exists; - ASSERT(exists.init("a").isOK()); + ExistsMatchExpression exists("a"); ASSERT(exists.matchesBSON(BSON("a" << BSON_ARRAY(4 << 5.5)), NULL)); } TEST(ExistsMatchExpression, ElemMatchKey) { - ExistsMatchExpression exists; - ASSERT(exists.init("a.b").isOK()); + ExistsMatchExpression exists("a.b"); MatchDetails details; details.requestElemMatchKey(); ASSERT(!exists.matchesBSON(BSON("a" << 1), &details)); @@ -1318,10 +1007,8 @@ TEST(ExistsMatchExpression, ElemMatchKey) { } TEST(ExistsMatchExpression, Equivalent) { - ExistsMatchExpression e1; - ExistsMatchExpression e2; - e1.init("a").transitional_ignore(); - e2.init("b").transitional_ignore(); + ExistsMatchExpression e1("a"); + ExistsMatchExpression e2("b"); ASSERT(e1.equivalent(&e1)); ASSERT(!e1.equivalent(&e2)); @@ -1331,7 +1018,7 @@ TEST(InMatchExpression, MatchesElementSingle) { BSONArray operand = BSON_ARRAY(1); BSONObj match = BSON("a" << 1); BSONObj notMatch = BSON("a" << 2); - InMatchExpression in; + InMatchExpression in(""); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); ASSERT(in.matchesSingleElement(match["a"])); @@ -1339,8 +1026,7 @@ TEST(InMatchExpression, MatchesElementSingle) { } TEST(InMatchExpression, MatchesEmpty) { - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); BSONObj notMatch = BSON("a" << 2); ASSERT(!in.matchesSingleElement(notMatch["a"])); @@ -1350,7 +1036,7 @@ TEST(InMatchExpression, MatchesEmpty) { TEST(InMatchExpression, MatchesElementMultiple) { BSONObj operand = BSON_ARRAY(1 << "r" << true << 1); - InMatchExpression in; + InMatchExpression in(""); std::vector<BSONElement> equalities{operand[0], operand[1], operand[2], operand[3]}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1368,8 +1054,7 @@ TEST(InMatchExpression, MatchesElementMultiple) { TEST(InMatchExpression, MatchesScalar) { BSONObj operand = BSON_ARRAY(5); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1379,8 +1064,7 @@ TEST(InMatchExpression, MatchesScalar) { TEST(InMatchExpression, MatchesArrayValue) { BSONObj operand = BSON_ARRAY(5); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1392,8 +1076,7 @@ TEST(InMatchExpression, MatchesArrayValue) { TEST(InMatchExpression, MatchesNull) { BSONObj operand = BSON_ARRAY(BSONNULL); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1407,16 +1090,14 @@ TEST(InMatchExpression, MatchesNull) { TEST(InMatchExpression, MatchesUndefined) { BSONObj operand = BSON_ARRAY(BSONUndefined); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_NOT_OK(in.setEqualities(std::move(equalities))); } TEST(InMatchExpression, MatchesMinKey) { BSONObj operand = BSON_ARRAY(MinKey); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1427,8 +1108,7 @@ TEST(InMatchExpression, MatchesMinKey) { TEST(InMatchExpression, MatchesMaxKey) { BSONObj operand = BSON_ARRAY(MaxKey); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1439,8 +1119,7 @@ TEST(InMatchExpression, MatchesMaxKey) { TEST(InMatchExpression, MatchesFullArray) { BSONObj operand = BSON_ARRAY(BSON_ARRAY(1 << 2) << 4 << 5); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand[0], operand[1], operand[2]}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1452,8 +1131,7 @@ TEST(InMatchExpression, MatchesFullArray) { TEST(InMatchExpression, ElemMatchKey) { BSONObj operand = BSON_ARRAY(5 << 2); - InMatchExpression in; - in.init("a").transitional_ignore(); + InMatchExpression in("a"); std::vector<BSONElement> equalities{operand[0], operand[1]}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1471,8 +1149,8 @@ TEST(InMatchExpression, ElemMatchKey) { TEST(InMatchExpression, InMatchExpressionsWithDifferentNumbersOfElementsAreUnequal) { BSONObj obj = BSON("" << "string"); - InMatchExpression eq1; - InMatchExpression eq2; + InMatchExpression eq1(""); + InMatchExpression eq2(""); std::vector<BSONElement> equalities{obj.firstElement()}; ASSERT_OK(eq1.setEqualities(std::move(equalities))); ASSERT(!eq1.equivalent(&eq2)); @@ -1480,20 +1158,20 @@ TEST(InMatchExpression, InMatchExpressionsWithDifferentNumbersOfElementsAreUnequ TEST(InMatchExpression, InMatchExpressionsWithUnequalCollatorsAreUnequal) { CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kReverseString); - InMatchExpression eq1; + InMatchExpression eq1(""); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression eq2; + InMatchExpression eq2(""); eq2.setCollator(&collator2); ASSERT(!eq1.equivalent(&eq2)); } TEST(InMatchExpression, InMatchExpressionsWithEqualCollatorsAreEqual) { CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression eq1; + InMatchExpression eq1(""); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression eq2; + InMatchExpression eq2(""); eq2.setCollator(&collator2); ASSERT(eq1.equivalent(&eq2)); } @@ -1504,10 +1182,10 @@ TEST(InMatchExpression, InMatchExpressionsWithCollationEquivalentElementsAreEqua BSONObj obj2 = BSON("" << "string2"); CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression eq1; + InMatchExpression eq1(""); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression eq2; + InMatchExpression eq2(""); eq2.setCollator(&collator2); std::vector<BSONElement> equalities1{obj1.firstElement()}; @@ -1525,10 +1203,10 @@ TEST(InMatchExpression, InMatchExpressionsWithCollationNonEquivalentElementsAreU BSONObj obj2 = BSON("" << "string2"); CollatorInterfaceMock collator1(CollatorInterfaceMock::MockType::kReverseString); - InMatchExpression eq1; + InMatchExpression eq1(""); eq1.setCollator(&collator1); CollatorInterfaceMock collator2(CollatorInterfaceMock::MockType::kReverseString); - InMatchExpression eq2; + InMatchExpression eq2(""); eq2.setCollator(&collator2); std::vector<BSONElement> equalities1{obj1.firstElement()}; @@ -1544,7 +1222,7 @@ TEST(InMatchExpression, StringMatchingWithNullCollatorUsesBinaryComparison) { BSONArray operand = BSON_ARRAY("string"); BSONObj notMatch = BSON("a" << "string2"); - InMatchExpression in; + InMatchExpression in(""); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); ASSERT(!in.matchesSingleElement(notMatch["a"])); @@ -1555,7 +1233,7 @@ TEST(InMatchExpression, StringMatchingRespectsCollation) { BSONObj match = BSON("a" << "string2"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); - InMatchExpression in; + InMatchExpression in(""); in.setCollator(&collator); std::vector<BSONElement> equalities{operand.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1569,7 +1247,7 @@ TEST(InMatchExpression, ChangingCollationAfterAddingEqualitiesPreservesEqualitie << "string2"); CollatorInterfaceMock collatorAlwaysEqual(CollatorInterfaceMock::MockType::kAlwaysEqual); CollatorInterfaceMock collatorReverseString(CollatorInterfaceMock::MockType::kReverseString); - InMatchExpression in; + InMatchExpression in(""); in.setCollator(&collatorAlwaysEqual); std::vector<BSONElement> equalities{obj1.firstElement(), obj2.firstElement()}; ASSERT_OK(in.setEqualities(std::move(equalities))); @@ -1605,15 +1283,11 @@ TEST(BitTestMatchExpression, DoesNotMatchOther) { BSONObj notMatch9 = fromjson("{a: ObjectId('000000000000000000000000')}"); // OID BSONObj notMatch10 = fromjson("{a: Date(54)}"); // Date - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositions); + BitsAllClearMatchExpression ballc("a", bitPositions); + BitsAnySetMatchExpression banys("a", bitPositions); + BitsAnyClearMatchExpression banyc("a", bitPositions); - ASSERT_OK(balls.init("a", bitPositions)); - ASSERT_OK(ballc.init("a", bitPositions)); - ASSERT_OK(banys.init("a", bitPositions)); - ASSERT_OK(banyc.init("a", bitPositions)); ASSERT_EQ((size_t)0, balls.numBitPositions()); ASSERT_EQ((size_t)0, ballc.numBitPositions()); ASSERT_EQ((size_t)0, banys.numBitPositions()); @@ -1665,15 +1339,11 @@ TEST(BitTestMatchExpression, MatchBinaryWithLongBitMask) { BSONObj match = fromjson("{a: {$binary: 'NgAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitMask); + BitsAllClearMatchExpression ballc("a", bitMask); + BitsAnySetMatchExpression banys("a", bitMask); + BitsAnyClearMatchExpression banyc("a", bitMask); - ASSERT_OK(balls.init("a", bitMask)); - ASSERT_OK(ballc.init("a", bitMask)); - ASSERT_OK(banys.init("a", bitMask)); - ASSERT_OK(banyc.init("a", bitMask)); std::vector<uint32_t> bitPositions = balls.getBitPositions(); ASSERT(balls.matchesSingleElement(match["a"])); ASSERT(!ballc.matchesSingleElement(match["a"])); @@ -1687,15 +1357,11 @@ TEST(BitTestMatchExpression, MatchLongWithBinaryBitMask) { BSONObj match = fromjson("{a: 54}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitMaskSet, 4); + BitsAllClearMatchExpression ballc("a", bitMaskClear, 9); + BitsAnySetMatchExpression banys("a", bitMaskSet, 4); + BitsAnyClearMatchExpression banyc("a", bitMaskClear, 9); - ASSERT_OK(balls.init("a", bitMaskSet, 4)); - ASSERT_OK(ballc.init("a", bitMaskClear, 9)); - ASSERT_OK(banys.init("a", bitMaskSet, 4)); - ASSERT_OK(banyc.init("a", bitMaskClear, 9)); ASSERT(balls.matchesSingleElement(match["a"])); ASSERT(ballc.matchesSingleElement(match["a"])); ASSERT(banys.matchesSingleElement(match["a"])); @@ -1710,15 +1376,11 @@ TEST(BitTestMatchExpression, MatchesEmpty) { BSONObj match3 = fromjson("{a: 54.0}"); BSONObj match4 = fromjson("{a: {$binary: '2AAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositions); + BitsAllClearMatchExpression ballc("a", bitPositions); + BitsAnySetMatchExpression banys("a", bitPositions); + BitsAnyClearMatchExpression banyc("a", bitPositions); - ASSERT_OK(balls.init("a", bitPositions)); - ASSERT_OK(ballc.init("a", bitPositions)); - ASSERT_OK(banys.init("a", bitPositions)); - ASSERT_OK(banyc.init("a", bitPositions)); ASSERT_EQ((size_t)0, balls.numBitPositions()); ASSERT_EQ((size_t)0, ballc.numBitPositions()); ASSERT_EQ((size_t)0, banys.numBitPositions()); @@ -1751,15 +1413,11 @@ TEST(BitTestMatchExpression, MatchesInteger) { BSONObj match2 = fromjson("{a: NumberLong(54)}"); BSONObj match3 = fromjson("{a: 54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)4, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)4, banys.numBitPositions()); @@ -1788,15 +1446,11 @@ TEST(BitTestMatchExpression, MatchesNegativeInteger) { BSONObj match2 = fromjson("{a: NumberLong(-54)}"); BSONObj match3 = fromjson("{a: -54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)5, balls.numBitPositions()); ASSERT_EQ((size_t)4, ballc.numBitPositions()); ASSERT_EQ((size_t)5, banys.numBitPositions()); @@ -1823,15 +1477,11 @@ TEST(BitTestMatchExpression, MatchesIntegerWithBitMask) { BSONObj match2 = fromjson("{a: NumberLong(54)}"); BSONObj match3 = fromjson("{a: 54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitMaskSet); + BitsAllClearMatchExpression ballc("a", bitMaskClear); + BitsAnySetMatchExpression banys("a", bitMaskSet); + BitsAnyClearMatchExpression banyc("a", bitMaskClear); - ASSERT_OK(balls.init("a", bitMaskSet)); - ASSERT_OK(ballc.init("a", bitMaskClear)); - ASSERT_OK(banys.init("a", bitMaskSet)); - ASSERT_OK(banyc.init("a", bitMaskClear)); ASSERT(balls.matchesSingleElement(match1["a"])); ASSERT(balls.matchesSingleElement(match2["a"])); ASSERT(balls.matchesSingleElement(match3["a"])); @@ -1854,15 +1504,11 @@ TEST(BitTestMatchExpression, MatchesNegativeIntegerWithBitMask) { BSONObj match2 = fromjson("{a: NumberLong(-54)}"); BSONObj match3 = fromjson("{a: -54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitMaskSet); + BitsAllClearMatchExpression ballc("a", bitMaskClear); + BitsAnySetMatchExpression banys("a", bitMaskSet); + BitsAnyClearMatchExpression banyc("a", bitMaskClear); - ASSERT_OK(balls.init("a", bitMaskSet)); - ASSERT_OK(ballc.init("a", bitMaskClear)); - ASSERT_OK(banys.init("a", bitMaskSet)); - ASSERT_OK(banyc.init("a", bitMaskClear)); ASSERT(balls.matchesSingleElement(match1["a"])); ASSERT(balls.matchesSingleElement(match2["a"])); ASSERT(balls.matchesSingleElement(match3["a"])); @@ -1887,15 +1533,11 @@ TEST(BitTestMatchExpression, DoesNotMatchInteger) { BSONObj match2 = fromjson("{a: NumberLong(54)}"); BSONObj match3 = fromjson("{a: 54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)5, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)5, banys.numBitPositions()); @@ -1922,15 +1564,11 @@ TEST(BitTestMatchExpression, DoesNotMatchIntegerWithBitMask) { BSONObj match2 = fromjson("{a: NumberLong(54)}"); BSONObj match3 = fromjson("{a: 54.0}"); - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitMaskSet); + BitsAllClearMatchExpression ballc("a", bitMaskClear); + BitsAnySetMatchExpression banys("a", bitMaskSet); + BitsAnyClearMatchExpression banyc("a", bitMaskClear); - ASSERT_OK(balls.init("a", bitMaskSet)); - ASSERT_OK(ballc.init("a", bitMaskClear)); - ASSERT_OK(banys.init("a", bitMaskSet)); - ASSERT_OK(banyc.init("a", bitMaskClear)); ASSERT(!balls.matchesSingleElement(match1["a"])); ASSERT(!balls.matchesSingleElement(match2["a"])); ASSERT(!balls.matchesSingleElement(match3["a"])); @@ -1956,15 +1594,11 @@ TEST(BitTestMatchExpression, MatchesBinary1) { BSONObj match2 = fromjson("{a: {$binary: 'NgAjqwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: 00110110... - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)4, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)4, banys.numBitPositions()); @@ -1990,15 +1624,11 @@ TEST(BitTestMatchExpression, MatchesBinary2) { BSONObj match2 = fromjson("{a: {$binary: 'JANgqwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: ........ 00000011 01100000 - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)4, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)4, banys.numBitPositions()); @@ -2022,14 +1652,11 @@ TEST(BitTestMatchExpression, MatchesBinaryWithBitMask) { BSONObj match2 = fromjson("{a: {$binary: 'JANgAwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: ........ 00000011 01100000 - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; - ASSERT_OK(balls.init("a", bas, 21)); - ASSERT_OK(ballc.init("a", bac, 21)); - ASSERT_OK(banys.init("a", bas, 21)); - ASSERT_OK(banyc.init("a", bac, 21)); + BitsAllSetMatchExpression balls("a", bas, 21); + BitsAllClearMatchExpression ballc("a", bac, 21); + BitsAnySetMatchExpression banys("a", bas, 21); + BitsAnyClearMatchExpression banyc("a", bac, 21); + ASSERT(balls.matchesSingleElement(match1["a"])); ASSERT(balls.matchesSingleElement(match2["a"])); ASSERT(ballc.matchesSingleElement(match1["a"])); @@ -2051,15 +1678,11 @@ TEST(BitTestMatchExpression, DoesNotMatchBinary1) { BSONObj match2 = fromjson("{a: {$binary: 'NgAjqwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: 00110110... - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)5, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)5, banys.numBitPositions()); @@ -2085,15 +1708,11 @@ TEST(BitTestMatchExpression, DoesNotMatchBinary2) { BSONObj match2 = fromjson("{a: {$binary: 'JANgqwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: ........ 00000011 01100000 - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; + BitsAllSetMatchExpression balls("a", bitPositionsSet); + BitsAllClearMatchExpression ballc("a", bitPositionsClear); + BitsAnySetMatchExpression banys("a", bitPositionsSet); + BitsAnyClearMatchExpression banyc("a", bitPositionsClear); - ASSERT_OK(balls.init("a", bitPositionsSet)); - ASSERT_OK(ballc.init("a", bitPositionsClear)); - ASSERT_OK(banys.init("a", bitPositionsSet)); - ASSERT_OK(banyc.init("a", bitPositionsClear)); ASSERT_EQ((size_t)5, balls.numBitPositions()); ASSERT_EQ((size_t)3, ballc.numBitPositions()); ASSERT_EQ((size_t)5, banys.numBitPositions()); @@ -2117,14 +1736,10 @@ TEST(BitTestMatchExpression, DoesNotMatchBinaryWithBitMask) { BSONObj match2 = fromjson("{a: {$binary: 'JANgAwetkqwklEWRbWERKKJREtbq', $type: '00'}}"); // Base64 to Binary: ........ 00000011 01100000 - BitsAllSetMatchExpression balls; - BitsAllClearMatchExpression ballc; - BitsAnySetMatchExpression banys; - BitsAnyClearMatchExpression banyc; - ASSERT_OK(balls.init("a", bas, 22)); - ASSERT_OK(ballc.init("a", bac, 22)); - ASSERT_OK(banys.init("a", bas, 22)); - ASSERT_OK(banyc.init("a", bac, 22)); + BitsAllSetMatchExpression balls("a", bas, 22); + BitsAllClearMatchExpression ballc("a", bac, 22); + BitsAnySetMatchExpression banys("a", bas, 22); + BitsAnyClearMatchExpression banyc("a", bac, 22); ASSERT(!balls.matchesSingleElement(match1["a"])); ASSERT(!balls.matchesSingleElement(match2["a"])); ASSERT(!ballc.matchesSingleElement(match1["a"])); diff --git a/src/mongo/db/matcher/expression_optimize_test.cpp b/src/mongo/db/matcher/expression_optimize_test.cpp index acbd7bc4ecb..93f7a49882f 100644 --- a/src/mongo/db/matcher/expression_optimize_test.cpp +++ b/src/mongo/db/matcher/expression_optimize_test.cpp @@ -339,7 +339,7 @@ TEST(ExpressionOptimizeTest, NormalizeWithInAndRegexPreservesTags) { TEST(ExpressionOptimizeTest, NormalizeWithInPreservesCollator) { CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); BSONObj obj = fromjson("{'': 'string'}"); - auto inMatchExpression = stdx::make_unique<InMatchExpression>(); + auto inMatchExpression = stdx::make_unique<InMatchExpression>(""); inMatchExpression->setCollator(&collator); std::vector<BSONElement> equalities{obj.firstElement()}; ASSERT_OK(inMatchExpression->setEqualities(std::move(equalities))); diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp index 6e7098a9b75..aad03b33342 100644 --- a/src/mongo/db/matcher/expression_parser.cpp +++ b/src/mongo/db/matcher/expression_parser.cpp @@ -218,37 +218,25 @@ StatusWithMatchExpression parseRegexElement(StringData name, BSONElement e) { if (e.type() != BSONType::RegEx) return {Status(ErrorCodes::BadValue, "not a regex")}; - auto temp = stdx::make_unique<RegexMatchExpression>(); - auto s = temp->init(name, e.regex(), e.regexFlags()); - if (!s.isOK()) - return s; - return {std::move(temp)}; + return {stdx::make_unique<RegexMatchExpression>(name, e.regex(), e.regexFlags())}; } StatusWithMatchExpression parseComparison( StringData name, - ComparisonMatchExpression* cmp, + std::unique_ptr<ComparisonMatchExpression> cmp, BSONElement e, const boost::intrusive_ptr<ExpressionContext>& expCtx, MatchExpressionParser::AllowedFeatureSet allowedFeatures) { - std::unique_ptr<ComparisonMatchExpression> temp(cmp); - // Non-equality comparison match expressions cannot have a regular expression as the argument. // (e.g. {a: {$gt: /b/}} is illegal). if (MatchExpression::EQ != cmp->matchType() && BSONType::RegEx == e.type()) { - return {Status(ErrorCodes::BadValue, - str::stream() << "Can't have RegEx as arg to predicate over field '" << name - << "'.")}; - } - - auto s = temp->init(name, e); - if (!s.isOK()) { - return s; + return {ErrorCodes::BadValue, + str::stream() << "Can't have RegEx as arg to predicate over field '" << name + << "'."}; } - temp->setCollator(expCtx->getCollator()); - - return {std::move(temp)}; + cmp->setCollator(expCtx->getCollator()); + return {std::move(cmp)}; } /** @@ -391,8 +379,12 @@ StatusWithMatchExpression parse(const BSONObj& obj, continue; } - auto eq = parseComparison( - e.fieldNameStringData(), new EqualityMatchExpression(), e, expCtx, allowedFeatures); + auto eq = + parseComparison(e.fieldNameStringData(), + stdx::make_unique<EqualityMatchExpression>(e.fieldNameStringData(), e), + e, + expCtx, + allowedFeatures); if (!eq.isOK()) return eq; @@ -467,11 +459,8 @@ StatusWithMatchExpression parseDBRef(StringData name, const ExtensionsCallback* extensionsCallback, MatchExpressionParser::AllowedFeatureSet allowedFeatures, DocumentParseLevel currentLevel) { - auto eq = stdx::make_unique<EqualityMatchExpression>(); - auto s = eq->init(elem.fieldName(), elem); - if (!s.isOK()) { - return s; - } + auto eq = stdx::make_unique<EqualityMatchExpression>(elem.fieldName(), elem); + // 'id' is collation-aware. 'ref' and 'db' are compared using binary comparison. eq->setCollator("id"_sd == name ? expCtx->getCollator() : nullptr); @@ -556,11 +545,7 @@ StatusWithMatchExpression parseMOD(StringData name, BSONElement e) { if (i.more()) return {Status(ErrorCodes::BadValue, "malformed mod, too many elements")}; - auto temp = stdx::make_unique<ModMatchExpression>(); - auto s = temp->init(name, d.numberInt(), r.numberInt()); - if (!s.isOK()) - return s; - return {std::move(temp)}; + return {stdx::make_unique<ModMatchExpression>(name, d.numberInt(), r.numberInt())}; } StatusWithMatchExpression parseRegexDocument(StringData name, const BSONObj& doc) { @@ -595,11 +580,7 @@ StatusWithMatchExpression parseRegexDocument(StringData name, const BSONObj& doc } } - auto temp = stdx::make_unique<RegexMatchExpression>(); - auto s = temp->init(name, regex, regexOptions); - if (!s.isOK()) - return s; - return {std::move(temp)}; + return {stdx::make_unique<RegexMatchExpression>(name, regex, regexOptions)}; } Status parseInExpression(InMatchExpression* inExpression, @@ -614,13 +595,10 @@ Status parseInExpression(InMatchExpression* inExpression, } if (e.type() == BSONType::RegEx) { - auto r = stdx::make_unique<RegexMatchExpression>(); - auto s = r->init("", e); - if (!s.isOK()) - return s; - s = inExpression->addRegex(std::move(r)); - if (!s.isOK()) - return s; + auto status = inExpression->addRegex(stdx::make_unique<RegexMatchExpression>(""_sd, e)); + if (!status.isOK()) { + return status; + } } else { equalities.push_back(e); } @@ -635,19 +613,12 @@ StatusWithMatchExpression parseType(StringData name, BSONElement elt) { return typeSet.getStatus(); } - auto typeExpr = stdx::make_unique<T>(); - if (typeSet.getValue().isEmpty()) { return {Status(ErrorCodes::FailedToParse, - str::stream() << typeExpr->name() << " must match at least one type")}; - } - - auto status = typeExpr->init(name, std::move(typeSet.getValue())); - if (!status.isOK()) { - return status; + str::stream() << name << " must match at least one type")}; } - return {std::move(typeExpr)}; + return {stdx::make_unique<T>(name, std::move(typeSet.getValue()))}; } /** @@ -722,41 +693,27 @@ StatusWith<std::vector<uint32_t>> parseBitPositionsArray(const BSONObj& theArray */ template <class T> StatusWithMatchExpression parseBitTest(StringData name, BSONElement e) { - auto bitTestMatchExpression = stdx::make_unique<T>(); + std::unique_ptr<BitTestMatchExpression> bitTestMatchExpression; if (e.type() == BSONType::Array) { // Array of bit positions provided as value. - auto statusWithBitPositions = parseBitPositionsArray(e.Obj()); - if (!statusWithBitPositions.isOK()) { - return statusWithBitPositions.getStatus(); - } - - std::vector<uint32_t> bitPositions = statusWithBitPositions.getValue(); - auto s = bitTestMatchExpression->init(name, bitPositions); - if (!s.isOK()) { - return s; + auto bitPositions = parseBitPositionsArray(e.Obj()); + if (!bitPositions.isOK()) { + return bitPositions.getStatus(); } + bitTestMatchExpression = stdx::make_unique<T>(name, std::move(bitPositions.getValue())); } else if (e.isNumber()) { // Integer bitmask provided as value. auto bitMask = MatchExpressionParser::parseIntegerElementToNonNegativeLong(e); if (!bitMask.isOK()) { return bitMask.getStatus(); } - - auto s = bitTestMatchExpression->init(name, bitMask.getValue()); - if (!s.isOK()) { - return s; - } + bitTestMatchExpression = stdx::make_unique<T>(name, bitMask.getValue()); } else if (e.type() == BSONType::BinData) { // Binary bitmask provided as value. - int eBinaryLen; auto eBinary = e.binData(eBinaryLen); - - auto s = bitTestMatchExpression->init(name, eBinary, eBinaryLen); - if (!s.isOK()) { - return s; - } + bitTestMatchExpression = stdx::make_unique<T>(name, eBinary, eBinaryLen); } else { return Status( ErrorCodes::BadValue, @@ -767,35 +724,36 @@ StatusWithMatchExpression parseBitTest(StringData name, BSONElement e) { } StatusWithMatchExpression parseInternalSchemaFmod(StringData name, BSONElement elem) { - auto path(name); + StringData path(name); if (elem.type() != BSONType::Array) return {ErrorCodes::BadValue, str::stream() << path << " must be an array, but got type " << elem.type()}; BSONObjIterator i(elem.embeddedObject()); - - if (!i.more()) + if (!i.more()) { return {ErrorCodes::BadValue, str::stream() << path << " does not have enough elements"}; + } auto d = i.next(); - if (!d.isNumber()) + if (!d.isNumber()) { return {ErrorCodes::TypeMismatch, str::stream() << path << " does not have a numeric divisor"}; + } - if (!i.more()) + if (!i.more()) { return {ErrorCodes::BadValue, str::stream() << path << " does not have enough elements"}; + } auto r = i.next(); - if (!d.isNumber()) + if (!d.isNumber()) { return {ErrorCodes::TypeMismatch, str::stream() << path << " does not have a numeric remainder"}; + } - if (i.more()) + if (i.more()) { return {ErrorCodes::BadValue, str::stream() << path << " has too many elements"}; + } - auto result = stdx::make_unique<InternalSchemaFmodMatchExpression>(); - auto s = result->init(name, d.numberDecimal(), r.numberDecimal()); - if (!s.isOK()) - return s; - return {std::move(result)}; + return {stdx::make_unique<InternalSchemaFmodMatchExpression>( + name, d.numberDecimal(), r.numberDecimal())}; } StatusWithMatchExpression parseInternalSchemaRootDocEq( @@ -817,8 +775,8 @@ StatusWithMatchExpression parseInternalSchemaRootDocEq( << " must be an object, found type " << elem.type())}; } - auto rootDocEq = stdx::make_unique<InternalSchemaRootDocEqMatchExpression>(); - rootDocEq->init(elem.embeddedObject()); + auto rootDocEq = + stdx::make_unique<InternalSchemaRootDocEqMatchExpression>(elem.embeddedObject()); return {std::move(rootDocEq)}; } @@ -834,13 +792,7 @@ StatusWithMatchExpression parseInternalSchemaSingleIntegerArgument(StringData na return parsedInt.getStatus(); } - auto matchExpression = stdx::make_unique<T>(); - auto status = matchExpression->init(name, parsedInt.getValue()); - if (!status.isOK()) { - return status; - } - - return {std::move(matchExpression)}; + return {stdx::make_unique<T>(name, parsedInt.getValue())}; } /** @@ -859,12 +811,7 @@ StatusWithMatchExpression parseTopLevelInternalSchemaSingleIntegerArgument( if (!parsedInt.isOK()) { return parsedInt.getStatus(); } - auto matchExpression = stdx::make_unique<T>(); - auto status = matchExpression->init(parsedInt.getValue()); - if (!status.isOK()) { - return status; - } - return {std::move(matchExpression)}; + return {stdx::make_unique<T>(parsedInt.getValue())}; } /** @@ -1102,17 +1049,11 @@ StatusWithMatchExpression parseInternalSchemaAllowedProperties( return properties.getStatus(); } - auto allowedPropertiesExpr = - stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>(); - auto status = allowedPropertiesExpr->init(std::move(properties.getValue()), - namePlaceholder.getValue(), - std::move(patternProperties.getValue()), - std::move(otherwise.getValue())); - if (!status.isOK()) { - return status; - } - - return {std::move(allowedPropertiesExpr)}; + return {stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>( + std::move(properties.getValue()), + namePlaceholder.getValue(), + std::move(patternProperties.getValue()), + std::move(otherwise.getValue()))}; } /** @@ -1163,13 +1104,8 @@ StatusWithMatchExpression parseInternalSchemaMatchArrayIndex( return expressionWithPlaceholder.getStatus(); } - auto matchArrayIndexExpr = stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>(); - auto initStatus = matchArrayIndexExpr->init( - path, index.getValue(), std::move(expressionWithPlaceholder.getValue())); - if (!initStatus.isOK()) { - return initStatus; - } - return {std::move(matchArrayIndexExpr)}; + return {stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>( + path, index.getValue(), std::move(expressionWithPlaceholder.getValue()))}; } StatusWithMatchExpression parseGeo(StringData name, @@ -1179,16 +1115,10 @@ StatusWithMatchExpression parseGeo(StringData name, if (PathAcceptingKeyword::WITHIN == type || PathAcceptingKeyword::GEO_INTERSECTS == type) { auto gq = stdx::make_unique<GeoExpression>(name.toString()); auto parseStatus = gq->parseFrom(section); - - if (!parseStatus.isOK()) - return StatusWithMatchExpression(parseStatus); - - auto e = stdx::make_unique<GeoMatchExpression>(); - - auto s = e->init(name, gq.release(), section); - if (!s.isOK()) - return StatusWithMatchExpression(s); - return {std::move(e)}; + if (!parseStatus.isOK()) { + return parseStatus; + } + return {stdx::make_unique<GeoMatchExpression>(name, gq.release(), section)}; } else { invariant(PathAcceptingKeyword::GEO_NEAR == type); @@ -1198,15 +1128,11 @@ StatusWithMatchExpression parseGeo(StringData name, } auto nq = stdx::make_unique<GeoNearExpression>(name.toString()); - auto s = nq->parseFrom(section); - if (!s.isOK()) { - return StatusWithMatchExpression(s); + auto status = nq->parseFrom(section); + if (!status.isOK()) { + return status; } - auto e = stdx::make_unique<GeoNearMatchExpression>(); - s = e->init(name, nq.release(), section); - if (!s.isOK()) - return StatusWithMatchExpression(s); - return {std::move(e)}; + return {stdx::make_unique<GeoNearMatchExpression>(name, nq.release(), section)}; } } @@ -1283,10 +1209,7 @@ StatusWithMatchExpression parseElemMatch(StringData name, if (!s.isOK()) return s; - auto temp = stdx::make_unique<ElemMatchValueMatchExpression>(); - s = temp->init(name); - if (!s.isOK()) - return s; + auto temp = stdx::make_unique<ElemMatchValueMatchExpression>(name); for (size_t i = 0; i < theAnd.numChildren(); i++) { temp->add(theAnd.getChild(i)); @@ -1314,12 +1237,7 @@ StatusWithMatchExpression parseElemMatch(StringData name, return {Status(ErrorCodes::BadValue, "$elemMatch cannot contain $where expression")}; } - auto temp = stdx::make_unique<ElemMatchObjectMatchExpression>(); - auto status = temp->init(name, sub.release()); - if (!status.isOK()) - return status; - - return {std::move(temp)}; + return {stdx::make_unique<ElemMatchObjectMatchExpression>(name, sub.release())}; } StatusWithMatchExpression parseAll(StringData name, @@ -1369,21 +1287,15 @@ StatusWithMatchExpression parseAll(StringData name, auto e = i.next(); if (e.type() == BSONType::RegEx) { - auto r = stdx::make_unique<RegexMatchExpression>(); - auto s = r->init(name, e); - if (!s.isOK()) - return s; - myAnd->add(r.release()); + auto expr = stdx::make_unique<RegexMatchExpression>(name, e); + myAnd->add(expr.release()); } else if (e.type() == BSONType::Object && MatchExpressionParser::parsePathAcceptingKeyword(e.Obj().firstElement())) { return {Status(ErrorCodes::BadValue, "no $ expressions in $all")}; } else { - auto x = stdx::make_unique<EqualityMatchExpression>(); - auto s = x->init(name, e); - if (!s.isOK()) - return s; - x->setCollator(expCtx->getCollator()); - myAnd->add(x.release()); + auto expr = stdx::make_unique<EqualityMatchExpression>(name, e); + expr->setCollator(expCtx->getCollator()); + myAnd->add(expr.release()); } } @@ -1442,9 +1354,7 @@ StatusWithMatchExpression parseInternalSchemaFixedArityArgument( ++position; } - auto parsedExpression = stdx::make_unique<T>(); - parsedExpression->init(std::move(expressions)); - return {std::move(parsedExpression)}; + return {stdx::make_unique<T>(std::move(expressions))}; } StatusWithMatchExpression parseNot(StringData name, @@ -1454,39 +1364,36 @@ StatusWithMatchExpression parseNot(StringData name, MatchExpressionParser::AllowedFeatureSet allowedFeatures, DocumentParseLevel currentLevel) { if (elem.type() == BSONType::RegEx) { - auto s = parseRegexElement(name, elem); - if (!s.isOK()) - return s; - auto n = stdx::make_unique<NotMatchExpression>(); - auto s2 = n->init(s.getValue().release()); - if (!s2.isOK()) - return StatusWithMatchExpression(s2); - return {std::move(n)}; + auto regex = parseRegexElement(name, elem); + if (!regex.isOK()) { + return regex; + } + return {stdx::make_unique<NotMatchExpression>(regex.getValue().release())}; } - if (elem.type() != BSONType::Object) - return StatusWithMatchExpression(ErrorCodes::BadValue, "$not needs a regex or a document"); + if (elem.type() != BSONType::Object) { + return {ErrorCodes::BadValue, "$not needs a regex or a document"}; + } auto notObject = elem.Obj(); - if (notObject.isEmpty()) - return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot be empty"); + if (notObject.isEmpty()) { + return {ErrorCodes::BadValue, "$not cannot be empty"}; + } auto theAnd = stdx::make_unique<AndMatchExpression>(); - auto s = parseSub( + auto parseStatus = parseSub( name, notObject, theAnd.get(), expCtx, extensionsCallback, allowedFeatures, currentLevel); - if (!s.isOK()) - return StatusWithMatchExpression(s); - - for (size_t i = 0; i < theAnd->numChildren(); i++) - if (theAnd->getChild(i)->matchType() == MatchExpression::REGEX) - return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot have a regex"); + if (!parseStatus.isOK()) { + return parseStatus; + } - auto theNot = stdx::make_unique<NotMatchExpression>(); - s = theNot->init(theAnd.release()); - if (!s.isOK()) - return StatusWithMatchExpression(s); + for (size_t i = 0; i < theAnd->numChildren(); i++) { + if (theAnd->getChild(i)->matchType() == MatchExpression::REGEX) { + return {ErrorCodes::BadValue, "$not cannot have a regex"}; + } + } - return {std::move(theNot)}; + return {stdx::make_unique<NotMatchExpression>(theAnd.release())}; } /** @@ -1503,7 +1410,8 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, MatchExpressionParser::AllowedFeatureSet allowedFeatures, DocumentParseLevel currentLevel) { if ("$eq"_sd == e.fieldNameStringData()) { - return parseComparison(name, new EqualityMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison( + name, stdx::make_unique<EqualityMatchExpression>(name, e), e, expCtx, allowedFeatures); } if ("$not"_sd == e.fieldNameStringData()) { @@ -1523,62 +1431,60 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, switch (*parseExpMatchType) { case PathAcceptingKeyword::LESS_THAN: - return parseComparison(name, new LTMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison( + name, stdx::make_unique<LTMatchExpression>(name, e), e, expCtx, allowedFeatures); case PathAcceptingKeyword::LESS_THAN_OR_EQUAL: - return parseComparison(name, new LTEMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison( + name, stdx::make_unique<LTEMatchExpression>(name, e), e, expCtx, allowedFeatures); case PathAcceptingKeyword::GREATER_THAN: - return parseComparison(name, new GTMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison( + name, stdx::make_unique<GTMatchExpression>(name, e), e, expCtx, allowedFeatures); case PathAcceptingKeyword::GREATER_THAN_OR_EQUAL: - return parseComparison(name, new GTEMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison( + name, stdx::make_unique<GTEMatchExpression>(name, e), e, expCtx, allowedFeatures); case PathAcceptingKeyword::NOT_EQUAL: { if (BSONType::RegEx == e.type()) { // Just because $ne can be rewritten as the negation of an equality does not mean // that $ne of a regex is allowed. See SERVER-1705. return {Status(ErrorCodes::BadValue, "Can't have regex as arg to $ne.")}; } - auto s = - parseComparison(name, new EqualityMatchExpression(), e, expCtx, allowedFeatures); - if (!s.isOK()) - return s; - auto n = stdx::make_unique<NotMatchExpression>(); - auto s2 = n->init(s.getValue().release()); - if (!s2.isOK()) - return s2; - return {std::move(n)}; + StatusWithMatchExpression s = + parseComparison(name, + stdx::make_unique<EqualityMatchExpression>(name, e), + e, + expCtx, + allowedFeatures); + return {stdx::make_unique<NotMatchExpression>(s.getValue().release())}; } case PathAcceptingKeyword::EQUALITY: - return parseComparison(name, new EqualityMatchExpression(), e, expCtx, allowedFeatures); + return parseComparison(name, + stdx::make_unique<EqualityMatchExpression>(name, e), + e, + expCtx, + allowedFeatures); case PathAcceptingKeyword::IN_EXPR: { - if (e.type() != BSONType::Array) + if (e.type() != BSONType::Array) { return {Status(ErrorCodes::BadValue, "$in needs an array")}; - auto temp = stdx::make_unique<InMatchExpression>(); - auto s = temp->init(name); - if (!s.isOK()) - return s; - s = parseInExpression(temp.get(), e.Obj(), expCtx); - if (!s.isOK()) - return s; + } + auto temp = stdx::make_unique<InMatchExpression>(name); + auto parseStatus = parseInExpression(temp.get(), e.Obj(), expCtx); + if (!parseStatus.isOK()) { + return parseStatus; + } return {std::move(temp)}; } case PathAcceptingKeyword::NOT_IN: { - if (e.type() != BSONType::Array) + if (e.type() != Array) { return {Status(ErrorCodes::BadValue, "$nin needs an array")}; - auto temp = stdx::make_unique<InMatchExpression>(); - auto s = temp->init(name); - if (!s.isOK()) - return s; - s = parseInExpression(temp.get(), e.Obj(), expCtx); - if (!s.isOK()) - return s; - - auto temp2 = stdx::make_unique<NotMatchExpression>(); - s = temp2->init(temp.release()); - if (!s.isOK()) - return s; - - return {std::move(temp2)}; + } + auto temp = stdx::make_unique<InMatchExpression>(name); + auto parseStatus = parseInExpression(temp.get(), e.Obj(), expCtx); + if (!parseStatus.isOK()) { + return parseStatus; + } + return {stdx::make_unique<NotMatchExpression>(temp.release())}; } case PathAcceptingKeyword::SIZE: { @@ -1601,31 +1507,24 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, } else { return {Status(ErrorCodes::BadValue, "$size needs a number")}; } + if (size < 0) { return {Status(ErrorCodes::BadValue, "$size may not be negative")}; } - - auto temp = stdx::make_unique<SizeMatchExpression>(); - auto s = temp->init(name, size); - if (!s.isOK()) - return s; - return {std::move(temp)}; + return {stdx::make_unique<SizeMatchExpression>(name, size)}; } case PathAcceptingKeyword::EXISTS: { - if (!e) + if (e.eoo()) { return {Status(ErrorCodes::BadValue, "$exists can't be eoo")}; - auto temp = stdx::make_unique<ExistsMatchExpression>(); - auto s = temp->init(name); - if (!s.isOK()) - return s; - if (e.trueValue()) - return {std::move(temp)}; - auto temp2 = stdx::make_unique<NotMatchExpression>(); - s = temp2->init(temp.release()); - if (!s.isOK()) - return s; - return {std::move(temp2)}; + } + + auto existsExpr = stdx::make_unique<ExistsMatchExpression>(name); + if (e.trueValue()) { + return {std::move(existsExpr)}; + } + + return {stdx::make_unique<NotMatchExpression>(existsExpr.release())}; } case PathAcceptingKeyword::TYPE: @@ -1711,12 +1610,8 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, return parsedSubObjExpr; } - auto expr = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto status = expr->init(std::move(parsedSubObjExpr.getValue()), name); - if (!status.isOK()) { - return status; - } - return {std::move(expr)}; + return {stdx::make_unique<InternalSchemaObjectMatchExpression>( + name, std::move(parsedSubObjExpr.getValue()))}; } case PathAcceptingKeyword::INTERNAL_SCHEMA_UNIQUE_ITEMS: { @@ -1725,12 +1620,7 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, str::stream() << name << " must be a boolean of value true"}; } - auto expr = stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(); - auto status = expr->init(name); - if (!status.isOK()) { - return status; - } - return {std::move(expr)}; + return {stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(name)}; } case PathAcceptingKeyword::INTERNAL_SCHEMA_MIN_LENGTH: { @@ -1808,14 +1698,8 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, if (!exprWithPlaceholder.isOK()) { return exprWithPlaceholder.getStatus(); } - - auto expr = stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>(); - auto status = - expr->init(name, parsedIndex.getValue(), std::move(exprWithPlaceholder.getValue())); - if (!status.isOK()) { - return status; - } - return {std::move(expr)}; + return {stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>( + name, parsedIndex.getValue(), std::move(exprWithPlaceholder.getValue()))}; } case PathAcceptingKeyword::INTERNAL_SCHEMA_TYPE: { @@ -1823,12 +1707,7 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, } case PathAcceptingKeyword::INTERNAL_SCHEMA_EQ: { - auto eqExpr = stdx::make_unique<InternalSchemaEqMatchExpression>(); - auto status = eqExpr->init(name, e); - if (!status.isOK()) { - return status; - } - return {std::move(eqExpr)}; + return {stdx::make_unique<InternalSchemaEqMatchExpression>(name, e)}; } } diff --git a/src/mongo/db/matcher/expression_parser_tree.cpp b/src/mongo/db/matcher/expression_parser_tree.cpp index 04680e16532..d8632e64fad 100644 --- a/src/mongo/db/matcher/expression_parser_tree.cpp +++ b/src/mongo/db/matcher/expression_parser_tree.cpp @@ -73,19 +73,16 @@ StatusWithMatchExpression MatchExpressionParser::_parseNot( StatusWithMatchExpression s = _parseRegexElement(name, e); if (!s.isOK()) return s; - std::unique_ptr<NotMatchExpression> n = stdx::make_unique<NotMatchExpression>(); - Status s2 = n->init(s.getValue().release()); - if (!s2.isOK()) - return StatusWithMatchExpression(s2); + std::unique_ptr<NotMatchExpression> n = + stdx::make_unique<NotMatchExpression>(s.getValue().release()); return {std::move(n)}; } - if (e.type() != Object) - return StatusWithMatchExpression(ErrorCodes::BadValue, "$not needs a regex or a document"); + uassert(ErrorCodes::BadValue, "$not needs a regex or a document", e.type() == Object); BSONObj notObject = e.Obj(); - if (notObject.isEmpty()) - return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot be empty"); + + uassert(ErrorCodes::BadValue, "$not cannot be empty", !notObject.isEmpty()); std::unique_ptr<AndMatchExpression> theAnd = stdx::make_unique<AndMatchExpression>(); Status s = _parseSub(name, notObject, theAnd.get(), expCtx, allowedFeatures, currentLevel); @@ -98,10 +95,8 @@ StatusWithMatchExpression MatchExpressionParser::_parseNot( if (theAnd->getChild(i)->matchType() == MatchExpression::REGEX) return StatusWithMatchExpression(ErrorCodes::BadValue, "$not cannot have a regex"); - std::unique_ptr<NotMatchExpression> theNot = stdx::make_unique<NotMatchExpression>(); - s = theNot->init(theAnd.release()); - if (!s.isOK()) - return StatusWithMatchExpression(s); + std::unique_ptr<NotMatchExpression> theNot = + stdx::make_unique<NotMatchExpression>(theAnd.release()); return {std::move(theNot)}; } diff --git a/src/mongo/db/matcher/expression_path.h b/src/mongo/db/matcher/expression_path.h index 4fb98d84d62..b0a1ee5354c 100644 --- a/src/mongo/db/matcher/expression_path.h +++ b/src/mongo/db/matcher/expression_path.h @@ -41,7 +41,10 @@ namespace mongo { */ class PathMatchExpression : public MatchExpression { public: - PathMatchExpression(MatchType matchType) : MatchExpression(matchType) {} + explicit PathMatchExpression(MatchType matchType, StringData path) + : MatchExpression(matchType), _path(path) { + _elementPath.init(_path); + } virtual ~PathMatchExpression() {} @@ -74,15 +77,13 @@ public: return _path; } - Status setPath(StringData path) { + void setPath(StringData path) { _path = path; - auto status = _elementPath.init(_path); - if (!status.isOK()) { - return status; - } + _elementPath.init(_path); + } + void setTraverseLeafArray() { _elementPath.setTraverseLeafArray(shouldExpandLeafArray()); - return Status::OK(); } /** @@ -98,7 +99,7 @@ public: for (auto rename : renameList) { if (rename.first == _path) { _rewrittenPath = rename.second; - invariantOK(setPath(_rewrittenPath)); + setPath(_rewrittenPath); ++renamesFound; } @@ -112,7 +113,7 @@ public: // Replace the chopped off components with the component names resulting from the // rename. _rewrittenPath = str::stream() << rename.second << "." << pathTail.toString(); - invariantOK(setPath(_rewrittenPath)); + setPath(_rewrittenPath); ++renamesFound; } diff --git a/src/mongo/db/matcher/expression_test.cpp b/src/mongo/db/matcher/expression_test.cpp index 9b65644042d..a6d8bbec44d 100644 --- a/src/mongo/db/matcher/expression_test.cpp +++ b/src/mongo/db/matcher/expression_test.cpp @@ -42,8 +42,7 @@ namespace mongo { TEST(LeafMatchExpressionTest, Equal1) { BSONObj temp = BSON("x" << 5); - EqualityMatchExpression e; - e.init("x", temp["x"]).transitional_ignore(); + EqualityMatchExpression e("x", temp["x"]); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 5 }"))); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : [5] }"))); @@ -61,8 +60,7 @@ TEST(LeafMatchExpressionTest, Comp1) { BSONObj temp = BSON("x" << 5); { - LTEMatchExpression e; - e.init("x", temp["x"]).transitional_ignore(); + LTEMatchExpression e("x", temp["x"]); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 5 }"))); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 4 }"))); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 6 }"))); @@ -70,8 +68,7 @@ TEST(LeafMatchExpressionTest, Comp1) { } { - LTMatchExpression e; - e.init("x", temp["x"]).transitional_ignore(); + LTMatchExpression e("x", temp["x"]); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 5 }"))); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 4 }"))); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 6 }"))); @@ -79,8 +76,7 @@ TEST(LeafMatchExpressionTest, Comp1) { } { - GTEMatchExpression e; - e.init("x", temp["x"]).transitional_ignore(); + GTEMatchExpression e("x", temp["x"]); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 5 }"))); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 4 }"))); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 6 }"))); @@ -88,8 +84,7 @@ TEST(LeafMatchExpressionTest, Comp1) { } { - GTMatchExpression e; - e.init("x", temp["x"]).transitional_ignore(); + GTMatchExpression e("x", temp["x"]); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 5 }"))); ASSERT_FALSE(e.matchesBSON(fromjson("{ x : 4 }"))); ASSERT_TRUE(e.matchesBSON(fromjson("{ x : 6 }"))); @@ -99,8 +94,7 @@ TEST(LeafMatchExpressionTest, Comp1) { TEST(MatchesBSONElement, ScalarEquality) { auto filterObj = fromjson("{i: 5}"); - EqualityMatchExpression filter; - ASSERT_OK(filter.init("i", filterObj["i"])); + EqualityMatchExpression filter("i", filterObj["i"]); auto aFive = fromjson("{a: 5}"); auto iFive = fromjson("{i: 5}"); @@ -140,8 +134,7 @@ TEST(MatchesBSONElement, ScalarEquality) { TEST(MatchesBSONElement, DottedPathEquality) { auto filterObj = fromjson("{'i.a': 5}"); - EqualityMatchExpression filter; - ASSERT_OK(filter.init("i.a", filterObj["i.a"])); + EqualityMatchExpression filter("i.a", filterObj["i.a"]); auto aFive = fromjson("{a: 5}"); auto iFive = fromjson("{i: 5}"); @@ -191,8 +184,7 @@ TEST(MatchesBSONElement, DottedPathEquality) { TEST(MatchesBSONElement, ArrayIndexEquality) { auto filterObj = fromjson("{'i.1': 5}"); - EqualityMatchExpression filter; - ASSERT_OK(filter.init("i.1", filterObj["i.1"])); + EqualityMatchExpression filter("i.1", filterObj["i.1"]); auto aFive = fromjson("{a: 5}"); auto iFive = fromjson("{i: 5}"); @@ -237,8 +229,7 @@ TEST(MatchesBSONElement, ArrayIndexEquality) { TEST(MatchesBSONElement, ObjectEquality) { auto filterObj = fromjson("{i: {a: 5}}"); - EqualityMatchExpression filter; - ASSERT_OK(filter.init("i", filterObj["i"])); + EqualityMatchExpression filter("i", filterObj["i"]); auto aFive = fromjson("{a: 5}"); auto iFive = fromjson("{i: 5}"); @@ -288,8 +279,7 @@ TEST(MatchesBSONElement, ObjectEquality) { TEST(MatchesBSONElement, ArrayEquality) { auto filterObj = fromjson("{i: [5]}"); - EqualityMatchExpression filter; - ASSERT_OK(filter.init("i", filterObj["i"])); + EqualityMatchExpression filter("i", filterObj["i"]); auto aFive = fromjson("{a: 5}"); auto iFive = fromjson("{i: 5}"); @@ -320,10 +310,10 @@ TEST(MatchesBSONElement, ArrayEquality) { TEST(MatchesBSONElement, LogicalExpression) { auto clauseObj1 = fromjson("{i: 5}"); auto clauseObj2 = fromjson("{'i.a': 6}"); - std::unique_ptr<ComparisonMatchExpression> clause1(new EqualityMatchExpression()); - ASSERT_OK(clause1->init("i", clauseObj1["i"])); - std::unique_ptr<ComparisonMatchExpression> clause2(new EqualityMatchExpression()); - ASSERT_OK(clause2->init("i.a", clauseObj2["i.a"])); + std::unique_ptr<ComparisonMatchExpression> clause1( + new EqualityMatchExpression("i", clauseObj1["i"])); + std::unique_ptr<ComparisonMatchExpression> clause2( + new EqualityMatchExpression("i.a", clauseObj2["i.a"])); OrMatchExpression filter; filter.add(clause1.release()); diff --git a/src/mongo/db/matcher/expression_text.cpp b/src/mongo/db/matcher/expression_text.cpp index 1719cda7a21..33c388bd607 100644 --- a/src/mongo/db/matcher/expression_text.cpp +++ b/src/mongo/db/matcher/expression_text.cpp @@ -42,9 +42,13 @@ namespace mongo { -Status TextMatchExpression::init(OperationContext* opCtx, - const NamespaceString& nss, - TextParams params) { +TextMatchExpression::TextMatchExpression(fts::FTSQueryImpl ftsQuery) + : TextMatchExpressionBase("_fts"), _ftsQuery(ftsQuery) {} + +TextMatchExpression::TextMatchExpression(OperationContext* opCtx, + const NamespaceString& nss, + TextParams params) + : TextMatchExpressionBase("_fts") { _ftsQuery.setQuery(std::move(params.query)); _ftsQuery.setLanguage(std::move(params.language)); _ftsQuery.setCaseSensitive(params.caseSensitive); @@ -56,28 +60,31 @@ Status TextMatchExpression::init(OperationContext* opCtx, AutoGetDb autoDb(opCtx, nss.db(), MODE_IS); Lock::CollectionLock collLock(opCtx->lockState(), nss.ns(), MODE_IS); Database* db = autoDb.getDb(); - if (!db) { - return {ErrorCodes::IndexNotFound, - str::stream() << "text index required for $text query (no such collection '" - << nss.ns() - << "')"}; - } + + uassert(ErrorCodes::IndexNotFound, + str::stream() << "text index required for $text query (no such collection '" + << nss.ns() + << "')", + db); + Collection* collection = db->getCollection(opCtx, nss); - if (!collection) { - return {ErrorCodes::IndexNotFound, - str::stream() << "text index required for $text query (no such collection '" - << nss.ns() - << "')"}; - } + + uassert(ErrorCodes::IndexNotFound, + str::stream() << "text index required for $text query (no such collection '" + << nss.ns() + << "')", + collection); + std::vector<IndexDescriptor*> idxMatches; collection->getIndexCatalog()->findIndexByType(opCtx, IndexNames::TEXT, idxMatches); - if (idxMatches.empty()) { - return {ErrorCodes::IndexNotFound, "text index required for $text query"}; - } - if (idxMatches.size() > 1) { - return {ErrorCodes::IndexNotFound, "more than one text index found for $text query"}; - } + + uassert( + ErrorCodes::IndexNotFound, "text index required for $text query", !idxMatches.empty()); + uassert(ErrorCodes::IndexNotFound, + "more than one text index found for $text query", + idxMatches.size() < 2); invariant(idxMatches.size() == 1); + IndexDescriptor* index = idxMatches[0]; const FTSAccessMethod* fam = static_cast<FTSAccessMethod*>(collection->getIndexCatalog()->getIndex(index)); @@ -91,19 +98,14 @@ Status TextMatchExpression::init(OperationContext* opCtx, } Status parseStatus = _ftsQuery.parse(version); - if (!parseStatus.isOK()) { - return parseStatus; - } - - return setPath("_fts"); + uassertStatusOK(parseStatus); } std::unique_ptr<MatchExpression> TextMatchExpression::shallowClone() const { - auto expr = stdx::make_unique<TextMatchExpression>(); - // We initialize _ftsQuery here directly rather than calling init(), to avoid needing to examine + auto expr = stdx::make_unique<TextMatchExpression>(_ftsQuery); + // We use the query-only constructor here directly rather than using the full constructor, to + // avoid needing to examine // the index catalog. - expr->_ftsQuery = _ftsQuery; - invariantOK(expr->setPath("_fts")); if (getTag()) { expr->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_text.h b/src/mongo/db/matcher/expression_text.h index 2a3ac4a3c36..1bf453906bd 100644 --- a/src/mongo/db/matcher/expression_text.h +++ b/src/mongo/db/matcher/expression_text.h @@ -41,7 +41,8 @@ class OperationContext; class TextMatchExpression : public TextMatchExpressionBase { public: - Status init(OperationContext* opCtx, const NamespaceString& nss, TextParams params); + explicit TextMatchExpression(fts::FTSQueryImpl ftsQuery); + TextMatchExpression(OperationContext* opCtx, const NamespaceString& nss, TextParams params); const fts::FTSQuery& getFTSQuery() const final { return _ftsQuery; diff --git a/src/mongo/db/matcher/expression_text_base.cpp b/src/mongo/db/matcher/expression_text_base.cpp index 625107d4aca..925d2bbb7a0 100644 --- a/src/mongo/db/matcher/expression_text_base.cpp +++ b/src/mongo/db/matcher/expression_text_base.cpp @@ -37,7 +37,8 @@ namespace mongo { const bool TextMatchExpressionBase::kCaseSensitiveDefault = false; const bool TextMatchExpressionBase::kDiacriticSensitiveDefault = false; -TextMatchExpressionBase::TextMatchExpressionBase() : LeafMatchExpression(TEXT) {} +TextMatchExpressionBase::TextMatchExpressionBase(StringData path) + : LeafMatchExpression(TEXT, path) {} void TextMatchExpressionBase::debugString(StringBuilder& debug, int level) const { const fts::FTSQuery& ftsQuery = getFTSQuery(); diff --git a/src/mongo/db/matcher/expression_text_base.h b/src/mongo/db/matcher/expression_text_base.h index ac51e137ee1..8c34126888e 100644 --- a/src/mongo/db/matcher/expression_text_base.h +++ b/src/mongo/db/matcher/expression_text_base.h @@ -51,7 +51,7 @@ public: static const bool kCaseSensitiveDefault; static const bool kDiacriticSensitiveDefault; - TextMatchExpressionBase(); + explicit TextMatchExpressionBase(StringData path); virtual ~TextMatchExpressionBase() {} /** diff --git a/src/mongo/db/matcher/expression_text_noop.cpp b/src/mongo/db/matcher/expression_text_noop.cpp index 5e6ef901b5c..a42845d4e63 100644 --- a/src/mongo/db/matcher/expression_text_noop.cpp +++ b/src/mongo/db/matcher/expression_text_noop.cpp @@ -34,13 +34,13 @@ namespace mongo { -Status TextNoOpMatchExpression::init(TextParams params) { +TextNoOpMatchExpression::TextNoOpMatchExpression(TextParams params) + : TextMatchExpressionBase("_fts") { _ftsQuery.setQuery(std::move(params.query)); _ftsQuery.setLanguage(std::move(params.language)); _ftsQuery.setCaseSensitive(params.caseSensitive); _ftsQuery.setDiacriticSensitive(params.diacriticSensitive); invariantOK(_ftsQuery.parse(fts::TEXT_INDEX_VERSION_INVALID)); - return setPath("_fts"); } std::unique_ptr<MatchExpression> TextNoOpMatchExpression::shallowClone() const { @@ -50,8 +50,7 @@ std::unique_ptr<MatchExpression> TextNoOpMatchExpression::shallowClone() const { params.caseSensitive = _ftsQuery.getCaseSensitive(); params.diacriticSensitive = _ftsQuery.getDiacriticSensitive(); - auto expr = stdx::make_unique<TextNoOpMatchExpression>(); - invariantOK(expr->init(std::move(params))); + auto expr = stdx::make_unique<TextNoOpMatchExpression>(std::move(params)); if (getTag()) { expr->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_text_noop.h b/src/mongo/db/matcher/expression_text_noop.h index 429fecff05d..3c2316595a9 100644 --- a/src/mongo/db/matcher/expression_text_noop.h +++ b/src/mongo/db/matcher/expression_text_noop.h @@ -35,7 +35,7 @@ namespace mongo { class TextNoOpMatchExpression : public TextMatchExpressionBase { public: - Status init(TextParams params); + explicit TextNoOpMatchExpression(TextParams params); const fts::FTSQuery& getFTSQuery() const final { return _ftsQuery; diff --git a/src/mongo/db/matcher/expression_tree.cpp b/src/mongo/db/matcher/expression_tree.cpp index df8ab0b4012..5e1a9f5d83d 100644 --- a/src/mongo/db/matcher/expression_tree.cpp +++ b/src/mongo/db/matcher/expression_tree.cpp @@ -122,8 +122,7 @@ MatchExpression::ExpressionOptimizerFunc ListOfMatchExpression::getOptimizer() c return std::unique_ptr<MatchExpression>(simplifiedExpression); } else if (matchType == NOR) { // Simplify NOR of exactly one operand to NOT of that operand. - auto simplifiedExpression = stdx::make_unique<NotMatchExpression>(); - invariantOK(simplifiedExpression->init(children.front())); + auto simplifiedExpression = stdx::make_unique<NotMatchExpression>(children.front()); children.clear(); return std::move(simplifiedExpression); } diff --git a/src/mongo/db/matcher/expression_tree.h b/src/mongo/db/matcher/expression_tree.h index 074ed6c728a..1368567e912 100644 --- a/src/mongo/db/matcher/expression_tree.h +++ b/src/mongo/db/matcher/expression_tree.h @@ -41,7 +41,7 @@ namespace mongo { class ListOfMatchExpression : public MatchExpression { public: - ListOfMatchExpression(MatchType type) : MatchExpression(type) {} + explicit ListOfMatchExpression(MatchType type) : MatchExpression(type) {} virtual ~ListOfMatchExpression(); /** @@ -187,19 +187,11 @@ public: class NotMatchExpression final : public MatchExpression { public: - NotMatchExpression() : MatchExpression(NOT) {} - NotMatchExpression(MatchExpression* e) : MatchExpression(NOT), _exp(e) {} - /** - * @param exp - I own it, and will delete - */ - virtual Status init(MatchExpression* exp) { - _exp.reset(exp); - return Status::OK(); - } + explicit NotMatchExpression(MatchExpression* e) : MatchExpression(NOT), _exp(e) {} virtual std::unique_ptr<MatchExpression> shallowClone() const { - std::unique_ptr<NotMatchExpression> self = stdx::make_unique<NotMatchExpression>(); - self->init(_exp->shallowClone().release()).transitional_ignore(); + std::unique_ptr<NotMatchExpression> self = + stdx::make_unique<NotMatchExpression>(_exp->shallowClone().release()); if (getTag()) { self->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_tree_test.cpp b/src/mongo/db/matcher/expression_tree_test.cpp index 6b65006cdd1..54e85206d75 100644 --- a/src/mongo/db/matcher/expression_tree_test.cpp +++ b/src/mongo/db/matcher/expression_tree_test.cpp @@ -43,20 +43,16 @@ using std::unique_ptr; TEST(NotMatchExpression, MatchesScalar) { BSONObj baseOperand = BSON("$lt" << 5); - unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression()); - ASSERT(lt->init("a", baseOperand["$lt"]).isOK()); - NotMatchExpression notOp; - ASSERT(notOp.init(lt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression("a", baseOperand["$lt"])); + NotMatchExpression notOp(lt.release()); ASSERT(notOp.matchesBSON(BSON("a" << 6), NULL)); ASSERT(!notOp.matchesBSON(BSON("a" << 4), NULL)); } TEST(NotMatchExpression, MatchesArray) { BSONObj baseOperand = BSON("$lt" << 5); - unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression()); - ASSERT(lt->init("a", baseOperand["$lt"]).isOK()); - NotMatchExpression notOp; - ASSERT(notOp.init(lt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression("a", baseOperand["$lt"])); + NotMatchExpression notOp(lt.release()); ASSERT(notOp.matchesBSON(BSON("a" << BSON_ARRAY(6)), NULL)); ASSERT(!notOp.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); // All array elements must match. @@ -65,10 +61,8 @@ TEST(NotMatchExpression, MatchesArray) { TEST(NotMatchExpression, ElemMatchKey) { BSONObj baseOperand = BSON("$lt" << 5); - unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression()); - ASSERT(lt->init("a", baseOperand["$lt"]).isOK()); - NotMatchExpression notOp; - ASSERT(notOp.init(lt.release()).isOK()); + unique_ptr<ComparisonMatchExpression> lt(new LTMatchExpression("a", baseOperand["$lt"])); + NotMatchExpression notOp(lt.release()); MatchDetails details; details.requestElemMatchKey(); ASSERT(!notOp.matchesBSON(BSON("a" << BSON_ARRAY(1)), &details)); @@ -83,10 +77,8 @@ TEST(NotMatchExpression, ElemMatchKey) { TEST(NotMatchExpression, SetCollatorPropagatesToChild) { BSONObj baseOperand = BSON("a" << "string"); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("a", baseOperand["a"]).isOK()); - NotMatchExpression notOp; - ASSERT(notOp.init(eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("a", baseOperand["a"])); + NotMatchExpression notOp(eq.release()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); notOp.setCollator(&collator); ASSERT(!notOp.matchesBSON(BSON("a" @@ -94,36 +86,6 @@ TEST(NotMatchExpression, SetCollatorPropagatesToChild) { nullptr)); } -/* - TEST( NotMatchExpression, MatchesIndexKey ) { - BSONObj baseOperand = BSON( "$lt" << 5 ); - unique_ptr<ComparisonMatchExpression> lt( new ComparisonMatchExpression() ); - ASSERT( lt->init( "a", baseOperand[ "$lt" ] ).isOK() ); - NotMatchExpression notOp; - ASSERT( notOp.init( lt.release() ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - BSONObj indexKey = BSON( "" << "7" ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - notOp.matchesIndexKey( indexKey, indexSpec ) ); - } -*/ - -/** -TEST( AndOp, MatchesElementSingleClause ) { - BSONObj baseOperand = BSON( "$lt" << 5 ); - BSONObj match = BSON( "a" << 4 ); - BSONObj notMatch = BSON( "a" << 5 ); - unique_ptr<ComparisonMatchExpression> lt( new ComparisonMatchExpression() ); - ASSERT( lt->init( "", baseOperand[ "$lt" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( lt.release() ); - AndOp andOp; - ASSERT( andOp.init( &subMatchExpressions ).isOK() ); - ASSERT( andOp.matchesSingleElement( match[ "a" ] ) ); - ASSERT( !andOp.matchesSingleElement( notMatch[ "a" ] ) ); -} -*/ - TEST(AndOp, NoClauses) { AndMatchExpression andMatchExpression; ASSERT(andMatchExpression.matchesBSON(BSONObj(), NULL)); @@ -143,12 +105,9 @@ TEST(AndOp, MatchesElementThreeClauses) { BSONObj notMatch3 = BSON("a" << "r"); - unique_ptr<ComparisonMatchExpression> sub1(new LTMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["$lt"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub2(new GTMatchExpression()); - ASSERT(sub2->init("a", baseOperand2["$gt"]).isOK()); - unique_ptr<RegexMatchExpression> sub3(new RegexMatchExpression()); - ASSERT(sub3->init("a", "1", "").isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new LTMatchExpression("a", baseOperand1["$lt"])); + unique_ptr<ComparisonMatchExpression> sub2(new GTMatchExpression("a", baseOperand2["$gt"])); + unique_ptr<RegexMatchExpression> sub3(new RegexMatchExpression("a", "1", "")); AndMatchExpression andOp; andOp.add(sub1.release()); @@ -163,10 +122,8 @@ TEST(AndOp, MatchesElementThreeClauses) { TEST(AndOp, MatchesSingleClause) { BSONObj baseOperand = BSON("$ne" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("a", baseOperand["$ne"]).isOK()); - unique_ptr<NotMatchExpression> ne(new NotMatchExpression()); - ASSERT(ne->init(eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("a", baseOperand["$ne"])); + unique_ptr<NotMatchExpression> ne(new NotMatchExpression(eq.release())); AndMatchExpression andOp; andOp.add(ne.release()); @@ -182,14 +139,9 @@ TEST(AndOp, MatchesThreeClauses) { BSONObj baseOperand2 = BSON("$lt" << 10); BSONObj baseOperand3 = BSON("$lt" << 100); - unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["$gt"]).isOK()); - - unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression()); - ASSERT(sub2->init("a", baseOperand2["$lt"]).isOK()); - - unique_ptr<ComparisonMatchExpression> sub3(new LTMatchExpression()); - ASSERT(sub3->init("b", baseOperand3["$lt"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression("a", baseOperand1["$gt"])); + unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression("a", baseOperand2["$lt"])); + unique_ptr<ComparisonMatchExpression> sub3(new LTMatchExpression("b", baseOperand3["$lt"])); AndMatchExpression andOp; andOp.add(sub1.release()); @@ -207,11 +159,8 @@ TEST(AndOp, ElemMatchKey) { BSONObj baseOperand1 = BSON("a" << 1); BSONObj baseOperand2 = BSON("b" << 2); - unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["a"]).isOK()); - - unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression()); - ASSERT(sub2->init("b", baseOperand2["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression("a", baseOperand1["a"])); + unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression("b", baseOperand2["b"])); AndMatchExpression andOp; andOp.add(sub1.release()); @@ -229,108 +178,15 @@ TEST(AndOp, ElemMatchKey) { ASSERT_EQUALS("1", details.elemMatchKey()); } -/** -TEST( AndOp, MatchesIndexKeyWithoutUnknown ) { - BSONObj baseOperand1 = BSON( "$gt" << 1 ); - BSONObj baseOperand2 = BSON( "$lt" << 5 ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$lt" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - AndOp andOp; - ASSERT( andOp.init( &subMatchExpressions ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - andOp.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - andOp.matchesIndexKey( BSON( "" << 0 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - andOp.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); -} - -TEST( AndOp, MatchesIndexKeyWithUnknown ) { - BSONObj baseOperand1 = BSON( "$gt" << 1 ); - BSONObj baseOperand2 = BSON( "$lt" << 5 ); - // This part will return PartialMatchResult_Unknown. - BSONObj baseOperand3 = BSON( "$ne" << 5 ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$lt" ] ).isOK() ); - unique_ptr<NeOp> sub3( new NeOp() ); - ASSERT( sub3->init( "a", baseOperand3[ "$ne" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - subMatchExpressions.mutableVector().push_back( sub3.release() ); - AndOp andOp; - ASSERT( andOp.init( &subMatchExpressions ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - andOp.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - andOp.matchesIndexKey( BSON( "" << 0 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - andOp.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); -} -*/ - -/** -TEST( OrOp, MatchesElementSingleClause ) { - BSONObj baseOperand = BSON( "$lt" << 5 ); - BSONObj match = BSON( "a" << 4 ); - BSONObj notMatch = BSON( "a" << 5 ); - unique_ptr<ComparisonMatchExpression> lt( new ComparisonMatchExpression() ); - ASSERT( lt->init( "a", baseOperand[ "$lt" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( lt.release() ); - OrOp orOp; - ASSERT( orOp.init( &subMatchExpressions ).isOK() ); - ASSERT( orOp.matchesSingleElement( match[ "a" ] ) ); - ASSERT( !orOp.matchesSingleElement( notMatch[ "a" ] ) ); -} -*/ - TEST(OrOp, NoClauses) { OrMatchExpression orOp; ASSERT(!orOp.matchesBSON(BSONObj(), NULL)); } -/* -TEST( OrOp, MatchesElementThreeClauses ) { - BSONObj baseOperand1 = BSON( "$lt" << 0 ); - BSONObj baseOperand2 = BSON( "$gt" << 10 ); - BSONObj baseOperand3 = BSON( "a" << 5 ); - BSONObj match1 = BSON( "a" << -1 ); - BSONObj match2 = BSON( "a" << 11 ); - BSONObj match3 = BSON( "a" << 5 ); - BSONObj notMatch = BSON( "a" << "6" ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$lt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub3( new ComparisonMatchExpression() ); - ASSERT( sub3->init( "a", baseOperand3[ "a" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - subMatchExpressions.mutableVector().push_back( sub3.release() ); - OrOp orOp; - ASSERT( orOp.init( &subMatchExpressions ).isOK() ); - ASSERT( orOp.matchesSingleElement( match1[ "a" ] ) ); - ASSERT( orOp.matchesSingleElement( match2[ "a" ] ) ); - ASSERT( orOp.matchesSingleElement( match3[ "a" ] ) ); - ASSERT( !orOp.matchesSingleElement( notMatch[ "a" ] ) ); -} -*/ + TEST(OrOp, MatchesSingleClause) { BSONObj baseOperand = BSON("$ne" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("a", baseOperand["$ne"]).isOK()); - unique_ptr<NotMatchExpression> ne(new NotMatchExpression()); - ASSERT(ne->init(eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("a", baseOperand["$ne"])); + unique_ptr<NotMatchExpression> ne(new NotMatchExpression(eq.release())); OrMatchExpression orOp; orOp.add(ne.release()); @@ -345,12 +201,9 @@ TEST(OrOp, MatchesThreeClauses) { BSONObj baseOperand1 = BSON("$gt" << 10); BSONObj baseOperand2 = BSON("$lt" << 0); BSONObj baseOperand3 = BSON("b" << 100); - unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["$gt"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression()); - ASSERT(sub2->init("a", baseOperand2["$lt"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub3(new EqualityMatchExpression()); - ASSERT(sub3->init("b", baseOperand3["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression("a", baseOperand1["$gt"])); + unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression("a", baseOperand2["$lt"])); + unique_ptr<ComparisonMatchExpression> sub3(new EqualityMatchExpression("b", baseOperand3["b"])); OrMatchExpression orOp; orOp.add(sub1.release()); @@ -369,10 +222,8 @@ TEST(OrOp, MatchesThreeClauses) { TEST(OrOp, ElemMatchKey) { BSONObj baseOperand1 = BSON("a" << 1); BSONObj baseOperand2 = BSON("b" << 2); - unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["a"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression()); - ASSERT(sub2->init("b", baseOperand2["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression("a", baseOperand1["a"])); + unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression("b", baseOperand2["b"])); OrMatchExpression orOp; orOp.add(sub1.release()); @@ -389,109 +240,15 @@ TEST(OrOp, ElemMatchKey) { ASSERT(!details.hasElemMatchKey()); } -/** -TEST( OrOp, MatchesIndexKeyWithoutUnknown ) { - BSONObj baseOperand1 = BSON( "$gt" << 5 ); - BSONObj baseOperand2 = BSON( "$lt" << 1 ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$lt" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - OrOp orOp; - ASSERT( orOp.init( &subMatchExpressions ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_False == - orOp.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - orOp.matchesIndexKey( BSON( "" << 0 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - orOp.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); -} - -TEST( OrOp, MatchesIndexKeyWithUnknown ) { - BSONObj baseOperand1 = BSON( "$gt" << 5 ); - BSONObj baseOperand2 = BSON( "$lt" << 1 ); - // This part will return PartialMatchResult_Unknown. - BSONObj baseOperand3 = BSON( "$ne" << 5 ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$lt" ] ).isOK() ); - unique_ptr<NeOp> sub3( new NeOp() ); - ASSERT( sub3->init( "a", baseOperand3[ "$ne" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - subMatchExpressions.mutableVector().push_back( sub3.release() ); - OrOp orOp; - ASSERT( orOp.init( &subMatchExpressions ).isOK() ); - IndexSpec indexSpec( BSON( "a" << 1 ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_Unknown == - orOp.matchesIndexKey( BSON( "" << 3 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - orOp.matchesIndexKey( BSON( "" << 0 ), indexSpec ) ); - ASSERT( MatchMatchExpression::PartialMatchResult_True == - orOp.matchesIndexKey( BSON( "" << 6 ), indexSpec ) ); -} -*/ - -/** -TEST( NorOp, MatchesElementSingleClause ) { - BSONObj baseOperand = BSON( "$lt" << 5 ); - BSONObj match = BSON( "a" << 5 ); - BSONObj notMatch = BSON( "a" << 4 ); - unique_ptr<ComparisonMatchExpression> lt( new ComparisonMatchExpression() ); - ASSERT( lt->init( "a", baseOperand[ "$lt" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( lt.release() ); - NorOp norOp; - ASSERT( norOp.init( &subMatchExpressions ).isOK() ); - ASSERT( norOp.matchesSingleElement( match[ "a" ] ) ); - ASSERT( !norOp.matchesSingleElement( notMatch[ "a" ] ) ); -} -*/ - TEST(NorOp, NoClauses) { NorMatchExpression norOp; ASSERT(norOp.matchesBSON(BSONObj(), NULL)); } -/* -TEST( NorOp, MatchesElementThreeClauses ) { - BSONObj baseOperand1 = BSON( "$lt" << 0 ); - BSONObj baseOperand2 = BSON( "$gt" << 10 ); - BSONObj baseOperand3 = BSON( "a" << 5 ); - BSONObj notMatch1 = BSON( "a" << -1 ); - BSONObj notMatch2 = BSON( "a" << 11 ); - BSONObj notMatch3 = BSON( "a" << 5 ); - BSONObj match = BSON( "a" << "6" ); - unique_ptr<ComparisonMatchExpression> sub1( new ComparisonMatchExpression() ); - ASSERT( sub1->init( "a", baseOperand1[ "$lt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub2( new ComparisonMatchExpression() ); - ASSERT( sub2->init( "a", baseOperand2[ "$gt" ] ).isOK() ); - unique_ptr<ComparisonMatchExpression> sub3( new ComparisonMatchExpression() ); - ASSERT( sub3->init( "a", baseOperand3[ "a" ] ).isOK() ); - std::vector<std::unique_ptr<<MatchMatchExpression>> subMatchExpressions; - subMatchExpressions.mutableVector().push_back( sub1.release() ); - subMatchExpressions.mutableVector().push_back( sub2.release() ); - subMatchExpressions.mutableVector().push_back( sub3.release() ); - NorOp norOp; - ASSERT( norOp.init( &subMatchExpressions ).isOK() ); - ASSERT( !norOp.matchesSingleElement( notMatch1[ "a" ] ) ); - ASSERT( !norOp.matchesSingleElement( notMatch2[ "a" ] ) ); - ASSERT( !norOp.matchesSingleElement( notMatch3[ "a" ] ) ); - ASSERT( norOp.matchesSingleElement( match[ "a" ] ) ); -} -*/ TEST(NorOp, MatchesSingleClause) { BSONObj baseOperand = BSON("$ne" << 5); - unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression()); - ASSERT(eq->init("a", baseOperand["$ne"]).isOK()); - unique_ptr<NotMatchExpression> ne(new NotMatchExpression()); - ASSERT(ne->init(eq.release()).isOK()); + unique_ptr<ComparisonMatchExpression> eq(new EqualityMatchExpression("a", baseOperand["$ne"])); + unique_ptr<NotMatchExpression> ne(new NotMatchExpression(eq.release())); NorMatchExpression norOp; norOp.add(ne.release()); @@ -507,12 +264,9 @@ TEST(NorOp, MatchesThreeClauses) { BSONObj baseOperand2 = BSON("$lt" << 0); BSONObj baseOperand3 = BSON("b" << 100); - unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["$gt"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression()); - ASSERT(sub2->init("a", baseOperand2["$lt"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub3(new EqualityMatchExpression()); - ASSERT(sub3->init("b", baseOperand3["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new GTMatchExpression("a", baseOperand1["$gt"])); + unique_ptr<ComparisonMatchExpression> sub2(new LTMatchExpression("a", baseOperand2["$lt"])); + unique_ptr<ComparisonMatchExpression> sub3(new EqualityMatchExpression("b", baseOperand3["b"])); NorMatchExpression norOp; norOp.add(sub1.release()); @@ -531,10 +285,8 @@ TEST(NorOp, MatchesThreeClauses) { TEST(NorOp, ElemMatchKey) { BSONObj baseOperand1 = BSON("a" << 1); BSONObj baseOperand2 = BSON("b" << 2); - unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression()); - ASSERT(sub1->init("a", baseOperand1["a"]).isOK()); - unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression()); - ASSERT(sub2->init("b", baseOperand2["b"]).isOK()); + unique_ptr<ComparisonMatchExpression> sub1(new EqualityMatchExpression("a", baseOperand1["a"])); + unique_ptr<ComparisonMatchExpression> sub2(new EqualityMatchExpression("b", baseOperand2["b"])); NorMatchExpression norOp; norOp.add(sub1.release()); @@ -555,10 +307,8 @@ TEST(NorOp, ElemMatchKey) { TEST(NorOp, Equivalent) { BSONObj baseOperand1 = BSON("a" << 1); BSONObj baseOperand2 = BSON("b" << 2); - EqualityMatchExpression sub1; - ASSERT(sub1.init("a", baseOperand1["a"]).isOK()); - EqualityMatchExpression sub2; - ASSERT(sub2.init("b", baseOperand2["b"]).isOK()); + EqualityMatchExpression sub1("a", baseOperand1["a"]); + EqualityMatchExpression sub2("b", baseOperand2["b"]); NorMatchExpression e1; e1.add(sub1.shallowClone().release()); diff --git a/src/mongo/db/matcher/expression_type.h b/src/mongo/db/matcher/expression_type.h index c9ac6a2129d..9ccdbe62b63 100644 --- a/src/mongo/db/matcher/expression_type.h +++ b/src/mongo/db/matcher/expression_type.h @@ -36,7 +36,8 @@ namespace mongo { template <class T> class TypeMatchExpressionBase : public LeafMatchExpression { public: - explicit TypeMatchExpressionBase(MatchType matchType) : LeafMatchExpression(matchType) {} + explicit TypeMatchExpressionBase(MatchType matchType, StringData path, MatcherTypeSet typeSet) + : LeafMatchExpression(matchType, path), _typeSet(std::move(typeSet)) {} virtual ~TypeMatchExpressionBase() = default; @@ -45,14 +46,8 @@ public: */ virtual StringData name() const = 0; - Status init(StringData path, MatcherTypeSet typeSet) { - _typeSet = std::move(typeSet); - return setPath(path); - } - std::unique_ptr<MatchExpression> shallowClone() const final { - auto expr = stdx::make_unique<T>(); - invariantOK(expr->init(path(), _typeSet)); + auto expr = stdx::make_unique<T>(path(), _typeSet); if (getTag()) { expr->setTag(getTag()->clone()); } @@ -117,7 +112,8 @@ class TypeMatchExpression final : public TypeMatchExpressionBase<TypeMatchExpres public: static constexpr StringData kName = "$type"_sd; - TypeMatchExpression() : TypeMatchExpressionBase(MatchExpression::TYPE_OPERATOR) {} + TypeMatchExpression(StringData path, MatcherTypeSet typeSet) + : TypeMatchExpressionBase(MatchExpression::TYPE_OPERATOR, path, typeSet) {} StringData name() const final { return kName; @@ -134,8 +130,10 @@ class InternalSchemaTypeExpression final public: static constexpr StringData kName = "$_internalSchemaType"_sd; - InternalSchemaTypeExpression() - : TypeMatchExpressionBase(MatchExpression::INTERNAL_SCHEMA_TYPE) {} + InternalSchemaTypeExpression(StringData path, MatcherTypeSet typeSet) + : TypeMatchExpressionBase(MatchExpression::INTERNAL_SCHEMA_TYPE, path, typeSet) { + setTraverseLeafArray(); + } StringData name() const final { return kName; diff --git a/src/mongo/db/matcher/expression_type_test.cpp b/src/mongo/db/matcher/expression_type_test.cpp index 91c8c7429be..e50f30b9b45 100644 --- a/src/mongo/db/matcher/expression_type_test.cpp +++ b/src/mongo/db/matcher/expression_type_test.cpp @@ -37,8 +37,7 @@ TEST(ExpressionTypeTest, MatchesElementStringType) { BSONObj match = BSON("a" << "abc"); BSONObj notMatch = BSON("a" << 5); - TypeMatchExpression type; - ASSERT(type.init("", String).isOK()); + TypeMatchExpression type("", String); ASSERT(type.matchesSingleElement(match["a"])); ASSERT(!type.matchesSingleElement(notMatch["a"])); } @@ -47,8 +46,7 @@ TEST(ExpressionTypeTest, MatchesElementNullType) { BSONObj match = BSON("a" << BSONNULL); BSONObj notMatch = BSON("a" << "abc"); - TypeMatchExpression type; - ASSERT(type.init("", jstNULL).isOK()); + TypeMatchExpression type("", jstNULL); ASSERT(type.matchesSingleElement(match["a"])); ASSERT(!type.matchesSingleElement(notMatch["a"])); } @@ -63,10 +61,10 @@ TEST(ExpressionTypeTest, MatchesElementNumber) { ASSERT_EQ(BSONType::NumberLong, match2["a"].type()); ASSERT_EQ(BSONType::NumberDouble, match3["a"].type()); - TypeMatchExpression typeExpr; MatcherTypeSet typeSet; typeSet.allNumbers = true; - ASSERT_OK(typeExpr.init("a", std::move(typeSet))); + TypeMatchExpression typeExpr("a", std::move(typeSet)); + ASSERT_EQ("a", typeExpr.path()); ASSERT_TRUE(typeExpr.matchesSingleElement(match1["a"])); ASSERT_TRUE(typeExpr.matchesSingleElement(match2["a"])); @@ -75,15 +73,13 @@ TEST(ExpressionTypeTest, MatchesElementNumber) { } TEST(ExpressionTypeTest, MatchesScalar) { - TypeMatchExpression type; - ASSERT(type.init("a", Bool).isOK()); + TypeMatchExpression type("a", Bool); ASSERT(type.matchesBSON(BSON("a" << true), NULL)); ASSERT(!type.matchesBSON(BSON("a" << 1), NULL)); } TEST(ExpressionTypeTest, MatchesArray) { - TypeMatchExpression type; - ASSERT(type.init("a", NumberInt).isOK()); + TypeMatchExpression type("a", NumberInt); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(4)), NULL)); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(4 << "a")), NULL)); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY("a" << 4)), NULL)); @@ -92,8 +88,7 @@ TEST(ExpressionTypeTest, MatchesArray) { } TEST(ExpressionTypeTest, TypeArrayMatchesOuterAndInnerArray) { - TypeMatchExpression type; - ASSERT(type.init("a", Array).isOK()); + TypeMatchExpression type("a", Array); ASSERT(type.matchesBSON(BSON("a" << BSONArray()), nullptr)); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(4 << "a")), nullptr)); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSONArray() << 2)), nullptr)); @@ -103,51 +98,44 @@ TEST(ExpressionTypeTest, TypeArrayMatchesOuterAndInnerArray) { } TEST(ExpressionTypeTest, MatchesObject) { - TypeMatchExpression type; - ASSERT(type.init("a", Object).isOK()); + TypeMatchExpression type("a", Object); ASSERT(type.matchesBSON(BSON("a" << BSON("b" << 1)), NULL)); ASSERT(!type.matchesBSON(BSON("a" << 1), NULL)); } TEST(ExpressionTypeTest, MatchesDotNotationFieldObject) { - TypeMatchExpression type; - ASSERT(type.init("a.b", Object).isOK()); + TypeMatchExpression type("a.b", Object); ASSERT(type.matchesBSON(BSON("a" << BSON("b" << BSON("c" << 1))), NULL)); ASSERT(!type.matchesBSON(BSON("a" << BSON("b" << 1)), NULL)); } TEST(ExpressionTypeTest, MatchesDotNotationArrayElementArray) { - TypeMatchExpression type; - ASSERT(type.init("a.0", Array).isOK()); + TypeMatchExpression type("a.0", Array); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(1))), NULL)); ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY("b")), NULL)); } TEST(ExpressionTypeTest, MatchesDotNotationArrayElementScalar) { - TypeMatchExpression type; - ASSERT(type.init("a.0", String).isOK()); + TypeMatchExpression type("a.0", String); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY("b")), NULL)); ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL)); } TEST(ExpressionTypeTest, MatchesDotNotationArrayElementObject) { - TypeMatchExpression type; - ASSERT(type.init("a.0", Object).isOK()); + TypeMatchExpression type("a.0", Object); ASSERT(type.matchesBSON(BSON("a" << BSON_ARRAY(BSON("b" << 1))), NULL)); ASSERT(!type.matchesBSON(BSON("a" << BSON_ARRAY(1)), NULL)); } TEST(ExpressionTypeTest, MatchesNull) { - TypeMatchExpression type; - ASSERT(type.init("a", jstNULL).isOK()); + TypeMatchExpression type("a", jstNULL); ASSERT(type.matchesBSON(BSON("a" << BSONNULL), NULL)); ASSERT(!type.matchesBSON(BSON("a" << 4), NULL)); ASSERT(!type.matchesBSON(BSONObj(), NULL)); } TEST(ExpressionTypeTest, ElemMatchKey) { - TypeMatchExpression type; - ASSERT(type.init("a.b", String).isOK()); + TypeMatchExpression type("a.b", String); MatchDetails details; details.requestElemMatchKey(); ASSERT(!type.matchesBSON(BSON("a" << 1), &details)); @@ -166,12 +154,9 @@ TEST(ExpressionTypeTest, ElemMatchKey) { } TEST(ExpressionTypeTest, Equivalent) { - TypeMatchExpression e1; - TypeMatchExpression e2; - TypeMatchExpression e3; - ASSERT_OK(e1.init("a", BSONType::String)); - ASSERT_OK(e2.init("a", BSONType::NumberDouble)); - ASSERT_OK(e3.init("b", BSONType::String)); + TypeMatchExpression e1("a", BSONType::String); + TypeMatchExpression e2("a", BSONType::NumberDouble); + TypeMatchExpression e3("b", BSONType::String); ASSERT(e1.equivalent(&e1)); ASSERT(!e1.equivalent(&e2)); @@ -179,8 +164,7 @@ TEST(ExpressionTypeTest, Equivalent) { } TEST(ExpressionTypeTest, InternalSchemaTypeArrayOnlyMatchesArrays) { - InternalSchemaTypeExpression expr; - ASSERT_OK(expr.init("a", BSONType::Array)); + InternalSchemaTypeExpression expr("a", BSONType::Array); ASSERT_TRUE(expr.matchesBSON(fromjson("{a: []}"))); ASSERT_TRUE(expr.matchesBSON(fromjson("{a: [1]}"))); ASSERT_TRUE(expr.matchesBSON(fromjson("{a: [{b: 1}, {b: 2}]}"))); @@ -189,10 +173,9 @@ TEST(ExpressionTypeTest, InternalSchemaTypeArrayOnlyMatchesArrays) { } TEST(ExpressionTypeTest, InternalSchemaTypeNumberDoesNotMatchArrays) { - InternalSchemaTypeExpression expr; MatcherTypeSet typeSet; typeSet.allNumbers = true; - ASSERT_OK(expr.init("a", std::move(typeSet))); + InternalSchemaTypeExpression expr("a", std::move(typeSet)); ASSERT_FALSE(expr.matchesBSON(fromjson("{a: []}"))); ASSERT_FALSE(expr.matchesBSON(fromjson("{a: [1]}"))); ASSERT_FALSE(expr.matchesBSON(fromjson("{a: ['b', 2, 3]}"))); @@ -202,12 +185,11 @@ TEST(ExpressionTypeTest, InternalSchemaTypeNumberDoesNotMatchArrays) { } TEST(ExpressionTypeTest, TypeExprWithMultipleTypesMatchesAllSuchTypes) { - TypeMatchExpression expr; MatcherTypeSet typeSet; typeSet.allNumbers = true; typeSet.bsonTypes.insert(BSONType::String); typeSet.bsonTypes.insert(BSONType::Object); - ASSERT_OK(expr.init("a", std::move(typeSet))); + TypeMatchExpression expr("a", std::move(typeSet)); ASSERT_FALSE(expr.matchesBSON(fromjson("{a: []}"))); ASSERT_TRUE(expr.matchesBSON(fromjson("{a: 1}"))); @@ -219,12 +201,11 @@ TEST(ExpressionTypeTest, TypeExprWithMultipleTypesMatchesAllSuchTypes) { } TEST(ExpressionTypeTest, InternalSchemaTypeExprWithMultipleTypesMatchesAllSuchTypes) { - InternalSchemaTypeExpression expr; MatcherTypeSet typeSet; typeSet.allNumbers = true; typeSet.bsonTypes.insert(BSONType::String); typeSet.bsonTypes.insert(BSONType::Object); - ASSERT_OK(expr.init("a", std::move(typeSet))); + InternalSchemaTypeExpression expr("a", std::move(typeSet)); ASSERT_FALSE(expr.matchesBSON(fromjson("{a: []}"))); ASSERT_TRUE(expr.matchesBSON(fromjson("{a: 1}"))); diff --git a/src/mongo/db/matcher/expression_where.cpp b/src/mongo/db/matcher/expression_where.cpp index 35f53f1ac14..dea7756f923 100644 --- a/src/mongo/db/matcher/expression_where.cpp +++ b/src/mongo/db/matcher/expression_where.cpp @@ -50,38 +50,24 @@ using std::string; using std::stringstream; using stdx::make_unique; -WhereMatchExpression::WhereMatchExpression(OperationContext* opCtx, WhereParams params) - : WhereMatchExpressionBase(std::move(params)), _opCtx(opCtx) { +WhereMatchExpression::WhereMatchExpression(OperationContext* opCtx, + WhereParams params, + StringData dbName) + : WhereMatchExpressionBase(std::move(params)), _dbName(dbName.toString()), _opCtx(opCtx) { invariant(_opCtx != NULL); - _func = 0; -} - -Status WhereMatchExpression::init(StringData dbName) { - if (!getGlobalScriptEngine()) { - return Status(ErrorCodes::BadValue, "no globalScriptEngine in $where parsing"); - } + uassert( + ErrorCodes::BadValue, "no globalScriptEngine in $where parsing", getGlobalScriptEngine()); - if (dbName.size() == 0) { - return Status(ErrorCodes::BadValue, "ns for $where cannot be empty"); - } - - _dbName = dbName.toString(); + uassert(ErrorCodes::BadValue, "ns for $where cannot be empty", dbName.size() != 0); const string userToken = AuthorizationSession::get(Client::getCurrent())->getAuthenticatedUserNamesToken(); - try { - _scope = getGlobalScriptEngine()->getPooledScope(_opCtx, _dbName, "where" + userToken); - _func = _scope->createFunction(getCode().c_str()); - } catch (...) { - return exceptionToStatus(); - } - - if (!_func) - return Status(ErrorCodes::BadValue, "$where compile error"); + _scope = getGlobalScriptEngine()->getPooledScope(_opCtx, _dbName, "where" + userToken); + _func = _scope->createFunction(getCode().c_str()); - return Status::OK(); + uassert(ErrorCodes::BadValue, "$where compile error", _func); } bool WhereMatchExpression::matches(const MatchableDocument* doc, MatchDetails* details) const { @@ -113,8 +99,7 @@ unique_ptr<MatchExpression> WhereMatchExpression::shallowClone() const { params.code = getCode(); params.scope = getScope(); unique_ptr<WhereMatchExpression> e = - make_unique<WhereMatchExpression>(_opCtx, std::move(params)); - uassertStatusOK(e->init(_dbName)); + make_unique<WhereMatchExpression>(_opCtx, std::move(params), _dbName); if (getTag()) { e->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/expression_where.h b/src/mongo/db/matcher/expression_where.h index 26b55e4f2ea..50062d6583a 100644 --- a/src/mongo/db/matcher/expression_where.h +++ b/src/mongo/db/matcher/expression_where.h @@ -37,9 +37,7 @@ class OperationContext; class WhereMatchExpression final : public WhereMatchExpressionBase { public: - WhereMatchExpression(OperationContext* opCtx, WhereParams params); - - Status init(StringData dbName); + WhereMatchExpression(OperationContext* opCtx, WhereParams params, StringData dbName); bool matches(const MatchableDocument* doc, MatchDetails* details = nullptr) const final; diff --git a/src/mongo/db/matcher/expression_where_base.h b/src/mongo/db/matcher/expression_where_base.h index 32033ea675a..12e7fd86322 100644 --- a/src/mongo/db/matcher/expression_where_base.h +++ b/src/mongo/db/matcher/expression_where_base.h @@ -42,7 +42,7 @@ public: BSONObj scope; // Owned. }; - WhereMatchExpressionBase(WhereParams params); + explicit WhereMatchExpressionBase(WhereParams params); size_t numChildren() const final { return 0; diff --git a/src/mongo/db/matcher/expression_where_noop.h b/src/mongo/db/matcher/expression_where_noop.h index 10235e3176f..0ee8a835c02 100644 --- a/src/mongo/db/matcher/expression_where_noop.h +++ b/src/mongo/db/matcher/expression_where_noop.h @@ -40,7 +40,7 @@ namespace mongo { */ class WhereNoOpMatchExpression final : public WhereMatchExpressionBase { public: - WhereNoOpMatchExpression(WhereParams params); + explicit WhereNoOpMatchExpression(WhereParams params); bool matches(const MatchableDocument* doc, MatchDetails* details = nullptr) const final; diff --git a/src/mongo/db/matcher/extensions_callback_noop.cpp b/src/mongo/db/matcher/extensions_callback_noop.cpp index 10026370e64..9662559ed07 100644 --- a/src/mongo/db/matcher/extensions_callback_noop.cpp +++ b/src/mongo/db/matcher/extensions_callback_noop.cpp @@ -41,11 +41,7 @@ StatusWithMatchExpression ExtensionsCallbackNoop::parseText(BSONElement text) co return textParams.getStatus(); } - auto expr = stdx::make_unique<TextNoOpMatchExpression>(); - Status initStatus = expr->init(std::move(textParams.getValue())); - if (!initStatus.isOK()) { - return initStatus; - } + auto expr = stdx::make_unique<TextNoOpMatchExpression>(std::move(textParams.getValue())); return {std::move(expr)}; } diff --git a/src/mongo/db/matcher/extensions_callback_real.cpp b/src/mongo/db/matcher/extensions_callback_real.cpp index f61928b4e2c..a962efe386a 100644 --- a/src/mongo/db/matcher/extensions_callback_real.cpp +++ b/src/mongo/db/matcher/extensions_callback_real.cpp @@ -45,11 +45,9 @@ StatusWithMatchExpression ExtensionsCallbackReal::parseText(BSONElement text) co return textParams.getStatus(); } - auto exp = stdx::make_unique<TextMatchExpression>(); - Status status = exp->init(_opCtx, *_nss, std::move(textParams.getValue())); - if (!status.isOK()) { - return status; - } + auto exp = + stdx::make_unique<TextMatchExpression>(_opCtx, *_nss, std::move(textParams.getValue())); + return {std::move(exp)}; } @@ -59,11 +57,8 @@ StatusWithMatchExpression ExtensionsCallbackReal::parseWhere(BSONElement where) return whereParams.getStatus(); } - auto exp = stdx::make_unique<WhereMatchExpression>(_opCtx, std::move(whereParams.getValue())); - Status status = exp->init(_nss->db()); - if (!status.isOK()) { - return status; - } + auto exp = stdx::make_unique<WhereMatchExpression>( + _opCtx, std::move(whereParams.getValue()), _nss->db()); return {std::move(exp)}; } diff --git a/src/mongo/db/matcher/path.cpp b/src/mongo/db/matcher/path.cpp index a55da25879d..8ecd2a99473 100644 --- a/src/mongo/db/matcher/path.cpp +++ b/src/mongo/db/matcher/path.cpp @@ -35,11 +35,10 @@ namespace mongo { -Status ElementPath::init(StringData path) { +void ElementPath::init(StringData path) { _shouldTraverseNonleafArrays = true; _shouldTraverseLeafArray = true; _fieldRef.parse(path); - return Status::OK(); } // ----- @@ -194,10 +193,8 @@ bool BSONElementIterator::subCursorHasMore() { } _subCursorPath.reset(new ElementPath()); - _subCursorPath - ->init(_arrayIterationState.restOfPath.substr( - _arrayIterationState.nextPieceOfPath.size() + 1)) - .transitional_ignore(); + _subCursorPath->init(_arrayIterationState.restOfPath.substr( + _arrayIterationState.nextPieceOfPath.size() + 1)); _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray()); // If we're here, we must be able to traverse nonleaf arrays. @@ -277,7 +274,7 @@ bool BSONElementIterator::more() { // The current array element is a subdocument. See if the subdocument generates // any elements matching the remaining subpath. _subCursorPath.reset(new ElementPath()); - _subCursorPath->init(_arrayIterationState.restOfPath).transitional_ignore(); + _subCursorPath->init(_arrayIterationState.restOfPath); _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray()); _subCursor.reset(new BSONElementIterator(_subCursorPath.get(), eltInArray.Obj())); @@ -303,10 +300,8 @@ bool BSONElementIterator::more() { // The current array element is itself an array. See if the nested array // has any elements matching the remainihng. _subCursorPath.reset(new ElementPath()); - _subCursorPath - ->init(_arrayIterationState.restOfPath.substr( - _arrayIterationState.nextPieceOfPath.size() + 1)) - .transitional_ignore(); + _subCursorPath->init(_arrayIterationState.restOfPath.substr( + _arrayIterationState.nextPieceOfPath.size() + 1)); _subCursorPath->setTraverseLeafArray(_path->shouldTraverseLeafArray()); BSONElementIterator* real = new BSONElementIterator( _subCursorPath.get(), _arrayIterationState._current.Obj()); diff --git a/src/mongo/db/matcher/path.h b/src/mongo/db/matcher/path.h index cb0c5fbe40c..b769bd35c7e 100644 --- a/src/mongo/db/matcher/path.h +++ b/src/mongo/db/matcher/path.h @@ -47,7 +47,7 @@ public: // TODO: replace uses of members below with regular construction. ElementPath() {} - Status init(StringData path); + void init(StringData path); void setTraverseNonleafArrays(bool b) { _shouldTraverseNonleafArrays = b; diff --git a/src/mongo/db/matcher/path_test.cpp b/src/mongo/db/matcher/path_test.cpp index 26bbed840f9..f66b4764fad 100644 --- a/src/mongo/db/matcher/path_test.cpp +++ b/src/mongo/db/matcher/path_test.cpp @@ -41,7 +41,7 @@ using std::string; TEST(Path, Root1) { ElementPath p; - ASSERT(p.init("a").isOK()); + p.init("a"); BSONObj doc = BSON("x" << 4 << "a" << 5); @@ -55,7 +55,7 @@ TEST(Path, Root1) { TEST(Path, RootArray1) { ElementPath p; - ASSERT(p.init("a").isOK()); + p.init("a"); BSONObj doc = BSON("x" << 4 << "a" << BSON_ARRAY(5 << 6)); @@ -78,7 +78,7 @@ TEST(Path, RootArray1) { TEST(Path, RootArray2) { ElementPath p; - ASSERT(p.init("a").isOK()); + p.init("a"); p.setTraverseLeafArray(false); BSONObj doc = BSON("x" << 4 << "a" << BSON_ARRAY(5 << 6)); @@ -94,7 +94,7 @@ TEST(Path, RootArray2) { TEST(Path, Nested1) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); BSONObj doc = BSON("a" << BSON_ARRAY(BSON("b" << 5) << 3 << BSONObj() << BSON("b" << BSON_ARRAY(9 << 11)) @@ -133,7 +133,7 @@ TEST(Path, Nested1) { TEST(Path, NestedPartialMatchScalar) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); BSONObj doc = BSON("a" << 4); @@ -152,7 +152,7 @@ TEST(Path, NestedPartialMatchScalar) { // what we want ideally. TEST(Path, NestedPartialMatchArray) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); BSONObj doc = BSON("a" << BSON_ARRAY(4)); @@ -164,7 +164,7 @@ TEST(Path, NestedPartialMatchArray) { // Note that this describes existing behavior and not necessarily TEST(Path, NestedEmptyArray) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); BSONObj doc = BSON("a" << BSON("b" << BSONArray())); @@ -180,7 +180,7 @@ TEST(Path, NestedEmptyArray) { TEST(Path, NestedNoLeaf1) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); p.setTraverseLeafArray(false); BSONObj doc = @@ -213,7 +213,7 @@ TEST(Path, NestedNoLeaf1) { TEST(Path, ArrayIndex1) { ElementPath p; - ASSERT(p.init("a.1").isOK()); + p.init("a.1"); BSONObj doc = BSON("a" << BSON_ARRAY(5 << 7 << 3)); @@ -228,7 +228,7 @@ TEST(Path, ArrayIndex1) { TEST(Path, ArrayIndex2) { ElementPath p; - ASSERT(p.init("a.1").isOK()); + p.init("a.1"); BSONObj doc = BSON("a" << BSON_ARRAY(5 << BSON_ARRAY(2 << 4) << 3)); @@ -243,7 +243,7 @@ TEST(Path, ArrayIndex2) { TEST(Path, ArrayIndex3) { ElementPath p; - ASSERT(p.init("a.1").isOK()); + p.init("a.1"); BSONObj doc = BSON("a" << BSON_ARRAY(5 << BSON("1" << 4) << 3)); @@ -262,7 +262,7 @@ TEST(Path, ArrayIndex3) { TEST(Path, ArrayIndexNested1) { ElementPath p; - ASSERT(p.init("a.1.b").isOK()); + p.init("a.1.b"); BSONObj doc = BSON("a" << BSON_ARRAY(5 << BSON("b" << 4) << 3)); @@ -282,7 +282,7 @@ TEST(Path, ArrayIndexNested1) { TEST(Path, ArrayIndexNested2) { ElementPath p; - ASSERT(p.init("a.1.b").isOK()); + p.init("a.1.b"); BSONObj doc = BSON("a" << BSON_ARRAY(5 << BSON_ARRAY(BSON("b" << 4)) << 3)); @@ -300,7 +300,7 @@ TEST(Path, ArrayIndexNested2) { // array containing subdocuments with nested arrays. TEST(Path, NonMatchingLongArrayOfSubdocumentsWithNestedArrays) { ElementPath p; - ASSERT(p.init("a.b.x").isOK()); + p.init("a.b.x"); // Build the document {a: [{b: []}, {b: []}, {b: []}, ...]}. BSONObj subdoc = BSON("b" << BSONArray()); @@ -321,7 +321,7 @@ TEST(Path, NonMatchingLongArrayOfSubdocumentsWithNestedArrays) { // outermost array that is implicitly traversed. TEST(Path, NestedArrayImplicitTraversal) { ElementPath p; - ASSERT(p.init("a.b").isOK()); + p.init("a.b"); BSONObj doc = fromjson("{a: [{b: [2, 3]}, {b: [4, 5]}]}"); BSONElementIterator cursor(&p, doc); @@ -369,7 +369,7 @@ TEST(Path, NestedArrayImplicitTraversal) { // current offset of the array being implicitly traversed. TEST(Path, ArrayOffsetWithImplicitAndExplicitTraversal) { ElementPath p; - ASSERT(p.init("a.0.b").isOK()); + p.init("a.0.b"); BSONObj doc = fromjson("{a: [{b: [2, 3]}, {b: [4, 5]}]}"); BSONElementIterator cursor(&p, doc); diff --git a/src/mongo/db/matcher/rewrite_expr.cpp b/src/mongo/db/matcher/rewrite_expr.cpp index 304a850f592..655384047bf 100644 --- a/src/mongo/db/matcher/rewrite_expr.cpp +++ b/src/mongo/db/matcher/rewrite_expr.cpp @@ -150,9 +150,8 @@ std::unique_ptr<MatchExpression> RewriteExpr::_rewriteInExpression( std::vector<BSONElement> elementList; inValues.elems(elementList); - auto matchInExpr = stdx::make_unique<InMatchExpression>(); + auto matchInExpr = stdx::make_unique<InMatchExpression>(fieldPath); matchInExpr->setCollator(_collator); - uassertStatusOK(matchInExpr->init(fieldPath)); uassertStatusOK(matchInExpr->setEqualities(elementList)); return std::move(matchInExpr); @@ -226,42 +225,46 @@ std::unique_ptr<MatchExpression> RewriteExpr::_buildComparisonMatchExpression( switch (comparisonOp) { case ExpressionCompare::EQ: { - compMatchExpr = stdx::make_unique<EqualityMatchExpression>(); + compMatchExpr = stdx::make_unique<EqualityMatchExpression>(fieldAndValue.fieldName(), + fieldAndValue); break; } case ExpressionCompare::NE: { - compMatchExpr = stdx::make_unique<EqualityMatchExpression>(); - notMatchExpr = stdx::make_unique<NotMatchExpression>(); + compMatchExpr = stdx::make_unique<EqualityMatchExpression>(fieldAndValue.fieldName(), + fieldAndValue); + notMatchExpr = stdx::make_unique<NotMatchExpression>(compMatchExpr.release()); break; } case ExpressionCompare::GT: { - compMatchExpr = stdx::make_unique<GTMatchExpression>(); + compMatchExpr = + stdx::make_unique<GTMatchExpression>(fieldAndValue.fieldName(), fieldAndValue); break; } case ExpressionCompare::GTE: { - compMatchExpr = stdx::make_unique<GTEMatchExpression>(); + compMatchExpr = + stdx::make_unique<GTEMatchExpression>(fieldAndValue.fieldName(), fieldAndValue); break; } case ExpressionCompare::LT: { - compMatchExpr = stdx::make_unique<LTMatchExpression>(); + compMatchExpr = + stdx::make_unique<LTMatchExpression>(fieldAndValue.fieldName(), fieldAndValue); break; } case ExpressionCompare::LTE: { - compMatchExpr = stdx::make_unique<LTEMatchExpression>(); + compMatchExpr = + stdx::make_unique<LTEMatchExpression>(fieldAndValue.fieldName(), fieldAndValue); break; } default: MONGO_UNREACHABLE; } - uassertStatusOK(compMatchExpr->init(fieldAndValue.fieldName(), fieldAndValue)); - compMatchExpr->setCollator(_collator); - if (notMatchExpr) { - uassertStatusOK(notMatchExpr->init(compMatchExpr.release())); + notMatchExpr->setCollator(_collator); return std::move(notMatchExpr); } + compMatchExpr->setCollator(_collator); return std::move(compMatchExpr); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.cpp index 6384bebe775..f6c84c6006e 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.cpp @@ -36,10 +36,18 @@ namespace mongo { constexpr StringData InternalSchemaAllElemMatchFromIndexMatchExpression::kName; +InternalSchemaAllElemMatchFromIndexMatchExpression:: + InternalSchemaAllElemMatchFromIndexMatchExpression( + StringData path, long long index, std::unique_ptr<ExpressionWithPlaceholder> expression) + : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_ALL_ELEM_MATCH_FROM_INDEX, + path), + _index(index), + _expression(std::move(expression)) {} + std::unique_ptr<MatchExpression> InternalSchemaAllElemMatchFromIndexMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>(); - invariantOK(clone->init(path(), _index, _expression->shallowClone())); + auto clone = stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>( + path(), _index, _expression->shallowClone()); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h index 625cf025583..ecc61250317 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_all_elem_match_from_index.h @@ -42,17 +42,8 @@ class InternalSchemaAllElemMatchFromIndexMatchExpression final public: static constexpr StringData kName = "$_internalSchemaAllElemMatchFromIndex"_sd; - InternalSchemaAllElemMatchFromIndexMatchExpression() - : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_ALL_ELEM_MATCH_FROM_INDEX) { - } - - Status init(StringData path, - long long index, - std::unique_ptr<ExpressionWithPlaceholder> expression) { - _index = index; - _expression = std::move(expression); - return setPath(path); - } + InternalSchemaAllElemMatchFromIndexMatchExpression( + StringData path, long long index, std::unique_ptr<ExpressionWithPlaceholder> expression); std::unique_ptr<MatchExpression> shallowClone() const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.cpp index 76244991508..5fa61fd23ea 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.cpp @@ -33,25 +33,23 @@ namespace mongo { constexpr StringData InternalSchemaAllowedPropertiesMatchExpression::kName; -Status InternalSchemaAllowedPropertiesMatchExpression::init( +InternalSchemaAllowedPropertiesMatchExpression::InternalSchemaAllowedPropertiesMatchExpression( boost::container::flat_set<StringData> properties, StringData namePlaceholder, std::vector<PatternSchema> patternProperties, - std::unique_ptr<ExpressionWithPlaceholder> otherwise) { - _properties = std::move(properties); - _namePlaceholder = namePlaceholder; - _patternProperties = std::move(patternProperties); - _otherwise = std::move(otherwise); + std::unique_ptr<ExpressionWithPlaceholder> otherwise) + : MatchExpression(MatchExpression::INTERNAL_SCHEMA_ALLOWED_PROPERTIES), + _properties(std::move(properties)), + _namePlaceholder(namePlaceholder), + _patternProperties(std::move(patternProperties)), + _otherwise(std::move(otherwise)) { for (auto&& constraint : _patternProperties) { const auto& errorStr = constraint.first.regex->error(); - if (!errorStr.empty()) { - return {ErrorCodes::BadValue, - str::stream() << "Invalid regular expression: " << errorStr}; - } + uassert(ErrorCodes::BadValue, + str::stream() << "Invalid regular expression: " << errorStr, + errorStr.empty()); } - - return Status::OK(); } void InternalSchemaAllowedPropertiesMatchExpression::debugString(StringBuilder& debug, @@ -165,11 +163,11 @@ std::unique_ptr<MatchExpression> InternalSchemaAllowedPropertiesMatchExpression: constraint.second->shallowClone()); } - auto clone = stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>(); - invariantOK(clone->init(_properties, - _namePlaceholder, - std::move(clonedPatternProperties), - _otherwise->shallowClone())); + auto clone = stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>( + _properties, + _namePlaceholder, + std::move(clonedPatternProperties), + _otherwise->shallowClone()); return {std::move(clone)}; } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h index b539318dfe8..89c7448ec79 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_allowed_properties.h @@ -108,13 +108,11 @@ public: static constexpr StringData kName = "$_internalSchemaAllowedProperties"_sd; - explicit InternalSchemaAllowedPropertiesMatchExpression() - : MatchExpression(MatchExpression::INTERNAL_SCHEMA_ALLOWED_PROPERTIES) {} - - Status init(boost::container::flat_set<StringData> properties, - StringData namePlaceholder, - std::vector<PatternSchema> patternProperties, - std::unique_ptr<ExpressionWithPlaceholder> otherwise); + explicit InternalSchemaAllowedPropertiesMatchExpression( + boost::container::flat_set<StringData> properties, + StringData namePlaceholder, + std::vector<PatternSchema> patternProperties, + std::unique_ptr<ExpressionWithPlaceholder> otherwise); void debugString(StringBuilder& debug, int level) const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_cond.h b/src/mongo/db/matcher/schema/expression_internal_schema_cond.h index 94da4bc3781..ab5f38b4d01 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_cond.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_cond.h @@ -41,8 +41,9 @@ class InternalSchemaCondMatchExpression final public: static constexpr StringData kName = "$_internalSchemaCond"_sd; - InternalSchemaCondMatchExpression() - : FixedArityMatchExpression(MatchType::INTERNAL_SCHEMA_COND) {} + explicit InternalSchemaCondMatchExpression( + std::array<std::unique_ptr<MatchExpression>, 3> expressions) + : FixedArityMatchExpression(MatchType::INTERNAL_SCHEMA_COND, std::move(expressions)) {} const MatchExpression* condition() const { return expressions()[0].get(); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp index f1a022da7c4..79d4a7c5d6e 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_cond_test.cpp @@ -43,8 +43,6 @@ namespace { std::unique_ptr<InternalSchemaCondMatchExpression> createCondMatchExpression(BSONObj condition, BSONObj thenBranch, BSONObj elseBranch) { - auto cond = stdx::make_unique<InternalSchemaCondMatchExpression>(); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); auto conditionExpr = MatchExpressionParser::parse(condition, expCtx); ASSERT_OK(conditionExpr.getStatus()); @@ -52,9 +50,12 @@ std::unique_ptr<InternalSchemaCondMatchExpression> createCondMatchExpression(BSO ASSERT_OK(thenBranchExpr.getStatus()); auto elseBranchExpr = MatchExpressionParser::parse(elseBranch, expCtx); - cond->init({{std::move(conditionExpr.getValue()), - std::move(thenBranchExpr.getValue()), - std::move(elseBranchExpr.getValue())}}); + std::array<std::unique_ptr<MatchExpression>, 3> expressions = { + {std::move(conditionExpr.getValue()), + std::move(thenBranchExpr.getValue()), + std::move(elseBranchExpr.getValue())}}; + + auto cond = stdx::make_unique<InternalSchemaCondMatchExpression>(std::move(expressions)); return cond; } @@ -103,9 +104,8 @@ TEST(InternalSchemaCondMatchExpressionTest, AppliesToSubobjectsViaObjectMatch) { auto elseQuery = BSON("interests" << "query optimization"); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK( - objMatch.init(createCondMatchExpression(conditionQuery, thenQuery, elseQuery), "job"_sd)); + InternalSchemaObjectMatchExpression objMatch( + "job"_sd, createCondMatchExpression(conditionQuery, thenQuery, elseQuery)); ASSERT_TRUE(objMatch.matchesBSON( fromjson("{name: 'anne', job: {team: 'engineering', subteam: 'query'}}"))); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_eq.cpp index 20de5d876e9..54ec03a0bed 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_eq.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq.cpp @@ -38,10 +38,10 @@ namespace mongo { constexpr StringData InternalSchemaEqMatchExpression::kName; -Status InternalSchemaEqMatchExpression::init(StringData path, BSONElement rhs) { - invariant(rhs); - _rhsElem = rhs; - return setPath(path); +InternalSchemaEqMatchExpression::InternalSchemaEqMatchExpression(StringData path, BSONElement rhs) + : LeafMatchExpression(MatchType::INTERNAL_SCHEMA_EQ, path), _rhsElem(rhs) { + invariant(_rhsElem); + setTraverseLeafArray(); } bool InternalSchemaEqMatchExpression::matchesSingleElement(const BSONElement& elem, @@ -78,8 +78,7 @@ bool InternalSchemaEqMatchExpression::equivalent(const MatchExpression* other) c } std::unique_ptr<MatchExpression> InternalSchemaEqMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaEqMatchExpression>(); - invariantOK(clone->init(path(), _rhsElem)); + auto clone = stdx::make_unique<InternalSchemaEqMatchExpression>(path(), _rhsElem); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq.h b/src/mongo/db/matcher/schema/expression_internal_schema_eq.h index 2f73ccf534e..a8f85a2843e 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_eq.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq.h @@ -45,9 +45,7 @@ class InternalSchemaEqMatchExpression final : public LeafMatchExpression { public: static constexpr StringData kName = "$_internalSchemaEq"_sd; - InternalSchemaEqMatchExpression() : LeafMatchExpression(MatchType::INTERNAL_SCHEMA_EQ) {} - - Status init(StringData path, BSONElement rhs); + InternalSchemaEqMatchExpression(StringData path, BSONElement rhs); std::unique_ptr<MatchExpression> shallowClone() const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp index 3ccc5175092..868c8337450 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_eq_test.cpp @@ -40,26 +40,24 @@ namespace { TEST(InternalSchemaEqMatchExpression, CorrectlyMatchesScalarElements) { BSONObj numberOperand = BSON("a" << 5); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", numberOperand["a"])); - ASSERT_TRUE(eq.matchesBSON(BSON("a" << 5.0))); - ASSERT_FALSE(eq.matchesBSON(BSON("a" << 6))); + InternalSchemaEqMatchExpression eqNumberOperand("a", numberOperand["a"]); + ASSERT_TRUE(eqNumberOperand.matchesBSON(BSON("a" << 5.0))); + ASSERT_FALSE(eqNumberOperand.matchesBSON(BSON("a" << 6))); BSONObj stringOperand = BSON("a" << "str"); - ASSERT_OK(eq.init("a", stringOperand["a"])); - ASSERT_TRUE(eq.matchesBSON(BSON("a" - << "str"))); - ASSERT_FALSE(eq.matchesBSON(BSON("a" - << "string"))); + InternalSchemaEqMatchExpression eqStringOperand("a", stringOperand["a"]); + ASSERT_TRUE(eqStringOperand.matchesBSON(BSON("a" + << "str"))); + ASSERT_FALSE(eqStringOperand.matchesBSON(BSON("a" + << "string"))); } TEST(InternalSchemaEqMatchExpression, CorrectlyMatchesArrayElement) { BSONObj operand = BSON("a" << BSON_ARRAY("b" << 5)); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_TRUE(eq.matchesBSON(BSON("a" << BSON_ARRAY("b" << 5)))); ASSERT_FALSE(eq.matchesBSON(BSON("a" << BSON_ARRAY(5 << "b")))); ASSERT_FALSE(eq.matchesBSON(BSON("a" << BSON_ARRAY("b" << 5 << 5)))); @@ -69,8 +67,7 @@ TEST(InternalSchemaEqMatchExpression, CorrectlyMatchesArrayElement) { TEST(InternalSchemaEqMatchExpression, CorrectlyMatchesNullElement) { BSONObj operand = BSON("a" << BSONNULL); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_TRUE(eq.matchesBSON(BSON("a" << BSONNULL))); ASSERT_FALSE(eq.matchesBSON(BSON("a" << 4))); } @@ -78,8 +75,7 @@ TEST(InternalSchemaEqMatchExpression, CorrectlyMatchesNullElement) { TEST(InternalSchemaEqMatchExpression, NullElementDoesNotMatchMissing) { BSONObj operand = BSON("a" << BSONNULL); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_FALSE(eq.matchesBSON(BSONObj())); ASSERT_FALSE(eq.matchesBSON(BSON("b" << 4))); } @@ -87,17 +83,14 @@ TEST(InternalSchemaEqMatchExpression, NullElementDoesNotMatchMissing) { TEST(InternalSchemaEqMatchExpression, NullElementDoesNotMatchUndefinedOrMissing) { BSONObj operand = BSON("a" << BSONNULL); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_FALSE(eq.matchesBSON(BSONObj())); ASSERT_FALSE(eq.matchesBSON(fromjson("{a: undefined}"))); } TEST(InternalSchemaEqMatchExpression, DoesNotTraverseLeafArrays) { BSONObj operand = BSON("a" << 5); - - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_TRUE(eq.matchesBSON(BSON("a" << 5.0))); ASSERT_FALSE(eq.matchesBSON(BSON("a" << BSON_ARRAY(5)))); } @@ -105,8 +98,7 @@ TEST(InternalSchemaEqMatchExpression, DoesNotTraverseLeafArrays) { TEST(InternalSchemaEqMatchExpression, MatchesObjectsIndependentOfFieldOrder) { BSONObj operand = fromjson("{a: {b: 1, c: {d: 2, e: 3}}}"); - InternalSchemaEqMatchExpression eq; - ASSERT_OK(eq.init("a", operand["a"])); + InternalSchemaEqMatchExpression eq("a", operand["a"]); ASSERT_TRUE(eq.matchesBSON(fromjson("{a: {b: 1, c: {d: 2, e: 3}}}"))); ASSERT_TRUE(eq.matchesBSON(fromjson("{a: {c: {e: 3, d: 2}, b: 1}}"))); ASSERT_FALSE(eq.matchesBSON(fromjson("{a: {b: 1, c: {d: 2}, e: 3}}"))); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_fmod.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_fmod.cpp index dcbe8c2b93b..3cc617d94bb 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_fmod.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_fmod.cpp @@ -36,21 +36,15 @@ namespace mongo { -Status InternalSchemaFmodMatchExpression::init(StringData path, - Decimal128 divisor, - Decimal128 remainder) { - if (divisor.isZero()) { - return Status(ErrorCodes::BadValue, "divisor cannot be 0"); - } - if (divisor.isNaN()) { - return Status(ErrorCodes::BadValue, "divisor cannot be NaN"); - } - if (divisor.isInfinite()) { - return Status(ErrorCodes::BadValue, "divisor cannot be infinite"); - } - _divisor = divisor; - _remainder = remainder; - return setPath(path); +InternalSchemaFmodMatchExpression::InternalSchemaFmodMatchExpression(StringData path, + Decimal128 divisor, + Decimal128 remainder) + : LeafMatchExpression(MatchType::INTERNAL_SCHEMA_FMOD, path), + _divisor(divisor), + _remainder(remainder) { + uassert(ErrorCodes::BadValue, "divisor cannot be 0", !divisor.isZero()); + uassert(ErrorCodes::BadValue, "divisor cannot be NaN", !divisor.isNaN()); + uassert(ErrorCodes::BadValue, "divisor cannot be infinite", !divisor.isInfinite()); } bool InternalSchemaFmodMatchExpression::matchesSingleElement(const BSONElement& e, diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_fmod.h b/src/mongo/db/matcher/schema/expression_internal_schema_fmod.h index 25a7b3c3945..6847913187d 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_fmod.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_fmod.h @@ -38,14 +38,11 @@ namespace mongo { */ class InternalSchemaFmodMatchExpression final : public LeafMatchExpression { public: - InternalSchemaFmodMatchExpression() : LeafMatchExpression(MatchType::INTERNAL_SCHEMA_FMOD) {} - - Status init(StringData path, Decimal128 divisor, Decimal128 remainder); + InternalSchemaFmodMatchExpression(StringData path, Decimal128 divisor, Decimal128 remainder); std::unique_ptr<MatchExpression> shallowClone() const final { std::unique_ptr<InternalSchemaFmodMatchExpression> m = - stdx::make_unique<InternalSchemaFmodMatchExpression>(); - invariantOK(m->init(path(), _divisor, _remainder)); + stdx::make_unique<InternalSchemaFmodMatchExpression>(path(), _divisor, _remainder); if (getTag()) { m->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_fmod_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_fmod_test.cpp index 2eef5fe0ed5..1701f0b8e29 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_fmod_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_fmod_test.cpp @@ -40,8 +40,7 @@ TEST(InternalSchemaFmodMatchExpression, MatchesElement) { BSONObj longLongMatch = BSON("a" << 68719476736LL); BSONObj notMatch = BSON("a" << 6); BSONObj negativeNotMatch = BSON("a" << -2); - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("", Decimal128(3), Decimal128(1))); + InternalSchemaFmodMatchExpression fmod("", Decimal128(3), Decimal128(1)); ASSERT_TRUE(fmod.matchesSingleElement(match.firstElement())); ASSERT_TRUE(fmod.matchesSingleElement(largerMatch.firstElement())); ASSERT_TRUE(fmod.matchesSingleElement(longLongMatch.firstElement())); @@ -50,49 +49,44 @@ TEST(InternalSchemaFmodMatchExpression, MatchesElement) { } TEST(InternalSchemaFmodMatchExpression, ZeroDivisor) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_NOT_OK(fmod.init("", Decimal128(0), Decimal128(1))); + ASSERT_THROWS_CODE(InternalSchemaFmodMatchExpression fmod("", Decimal128(0), Decimal128(1)), + AssertionException, + ErrorCodes::BadValue); } TEST(InternalSchemaFmodMatchExpression, MatchesScalar) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(5), Decimal128(2))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(5), Decimal128(2)); ASSERT_TRUE(fmod.matchesBSON(BSON("a" << 7.0))); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << 4))); } TEST(InternalSchemaFmodMatchExpression, MatchesNonIntegralValue) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(10.5), Decimal128((4.5)))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(10.5), Decimal128((4.5))); ASSERT_TRUE(fmod.matchesBSON(BSON("a" << 15.0))); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << 10.0))); } TEST(InternalSchemaFmodMatchExpression, MatchesArrayValue) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(5), Decimal128(2))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(5), Decimal128(2)); ASSERT_TRUE(fmod.matchesBSON(BSON("a" << BSON_ARRAY(5 << 12LL)))); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << BSON_ARRAY(6 << 8)))); } TEST(InternalSchemaFmodMatchExpression, DoesNotMatchNull) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(5), Decimal128(2))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(5), Decimal128(2)); ASSERT_FALSE(fmod.matchesBSON(BSONObj())); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << BSONNULL))); } TEST(InternalSchemaFmodMatchExpression, NegativeRemainders) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(5), Decimal128(-2.4))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(5), Decimal128(-2.4)); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << 7.6))); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << 12.4))); ASSERT_TRUE(fmod.matchesBSON(BSON("a" << Decimal128(-12.4)))); } TEST(InternalSchemaFmodMatchExpression, ElemMatchKey) { - InternalSchemaFmodMatchExpression fmod; - ASSERT_OK(fmod.init("a", Decimal128(5), Decimal128(2))); + InternalSchemaFmodMatchExpression fmod("a", Decimal128(5), Decimal128(2)); MatchDetails details; details.requestElemMatchKey(); ASSERT_FALSE(fmod.matchesBSON(BSON("a" << 4), &details)); @@ -105,15 +99,10 @@ TEST(InternalSchemaFmodMatchExpression, ElemMatchKey) { } TEST(InternalSchemaFmodMatchExpression, Equality) { - InternalSchemaFmodMatchExpression m1; - InternalSchemaFmodMatchExpression m2; - InternalSchemaFmodMatchExpression m3; - InternalSchemaFmodMatchExpression m4; - - ASSERT_OK(m1.init("a", Decimal128(1.7), Decimal128(2))); - ASSERT_OK(m2.init("a", Decimal128(2), Decimal128(2))); - ASSERT_OK(m3.init("a", Decimal128(1.7), Decimal128(1))); - ASSERT_OK(m4.init("b", Decimal128(1.7), Decimal128(2))); + InternalSchemaFmodMatchExpression m1("a", Decimal128(1.7), Decimal128(2)); + InternalSchemaFmodMatchExpression m2("a", Decimal128(2), Decimal128(2)); + InternalSchemaFmodMatchExpression m3("a", Decimal128(1.7), Decimal128(1)); + InternalSchemaFmodMatchExpression m4("b", Decimal128(1.7), Decimal128(2)); ASSERT_TRUE(m1.equivalent(&m1)); ASSERT_FALSE(m1.equivalent(&m2)); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.cpp index c081792b4f1..0bca92144be 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.cpp @@ -33,6 +33,14 @@ namespace mongo { constexpr StringData InternalSchemaMatchArrayIndexMatchExpression::kName; +InternalSchemaMatchArrayIndexMatchExpression::InternalSchemaMatchArrayIndexMatchExpression( + StringData path, long long index, std::unique_ptr<ExpressionWithPlaceholder> expression) + : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_MATCH_ARRAY_INDEX, path), + _index(index), + _expression(std::move(expression)) { + invariant(static_cast<bool>(_expression)); +} + void InternalSchemaMatchArrayIndexMatchExpression::debugString(StringBuilder& debug, int level) const { _debugAddSpace(debug, level); @@ -59,14 +67,6 @@ bool InternalSchemaMatchArrayIndexMatchExpression::equivalent(const MatchExpress _expression->equivalent(other->_expression.get()); } -Status InternalSchemaMatchArrayIndexMatchExpression::init( - StringData path, long long index, std::unique_ptr<ExpressionWithPlaceholder> expression) { - invariant(static_cast<bool>(expression)); - _index = index; - _expression = std::move(expression); - return setPath(path); -} - void InternalSchemaMatchArrayIndexMatchExpression::serialize(BSONObjBuilder* builder) const { BSONObjBuilder pathSubobj(builder->subobjStart(path())); { @@ -85,8 +85,11 @@ void InternalSchemaMatchArrayIndexMatchExpression::serialize(BSONObjBuilder* bui std::unique_ptr<MatchExpression> InternalSchemaMatchArrayIndexMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>(); - invariantOK(clone->init(path(), _index, _expression->shallowClone())); + auto clone = stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>( + path(), _index, _expression->shallowClone()); + if (getTag()) { + clone->setTag(getTag()->clone()); + } return std::move(clone); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h index 520ccae568c..8b75d91374d 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_match_array_index.h @@ -41,12 +41,8 @@ class InternalSchemaMatchArrayIndexMatchExpression final : public ArrayMatchingM public: static constexpr StringData kName = "$_internalSchemaMatchArrayIndex"_sd; - InternalSchemaMatchArrayIndexMatchExpression() - : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_MATCH_ARRAY_INDEX) {} - - Status init(StringData path, - long long index, - std::unique_ptr<ExpressionWithPlaceholder> expression); + InternalSchemaMatchArrayIndexMatchExpression( + StringData path, long long index, std::unique_ptr<ExpressionWithPlaceholder> expression); void debugString(StringBuilder& debug, int level) const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_max_items.h index 3ba965e298a..814aba1da84 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_items.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_items.h @@ -39,9 +39,9 @@ namespace mongo { class InternalSchemaMaxItemsMatchExpression final : public InternalSchemaNumArrayItemsMatchExpression { public: - InternalSchemaMaxItemsMatchExpression() - : InternalSchemaNumArrayItemsMatchExpression(INTERNAL_SCHEMA_MAX_ITEMS, - "$_internalSchemaMaxItems"_sd) {} + InternalSchemaMaxItemsMatchExpression(StringData path, long long numItems) + : InternalSchemaNumArrayItemsMatchExpression( + INTERNAL_SCHEMA_MAX_ITEMS, path, numItems, "$_internalSchemaMaxItems"_sd) {} bool matchesArray(const BSONObj& anArray, MatchDetails* details) const final { return (anArray.nFields() <= numItems()); @@ -49,8 +49,7 @@ public: std::unique_ptr<MatchExpression> shallowClone() const final { std::unique_ptr<InternalSchemaMaxItemsMatchExpression> maxItems = - stdx::make_unique<InternalSchemaMaxItemsMatchExpression>(); - invariantOK(maxItems->init(path(), numItems())); + stdx::make_unique<InternalSchemaMaxItemsMatchExpression>(path(), numItems()); if (getTag()) { maxItems->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp index 27675889dee..88aa6ea1f48 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_items_test.cpp @@ -37,8 +37,7 @@ namespace mongo { namespace { TEST(InternalSchemaMaxItemsMatchExpression, RejectsNonArrayElements) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 1)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 1); ASSERT(!maxItems.matchesBSON(BSON("a" << BSONObj()))); ASSERT(!maxItems.matchesBSON(BSON("a" << 1))); @@ -47,46 +46,40 @@ TEST(InternalSchemaMaxItemsMatchExpression, RejectsNonArrayElements) { } TEST(InternalSchemaMaxItemsMatchExpression, RejectsArraysWithTooManyElements) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 0)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 0); ASSERT(!maxItems.matchesBSON(BSON("a" << BSON_ARRAY(1)))); ASSERT(!maxItems.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)))); } TEST(InternalSchemaMaxItemsMatchExpression, AcceptsArrayWithLessThanOrEqualToMaxElements) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 2)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 2); ASSERT(maxItems.matchesBSON(BSON("a" << BSON_ARRAY(5 << 6)))); ASSERT(maxItems.matchesBSON(BSON("a" << BSON_ARRAY(5)))); } TEST(InternalSchemaMaxItemsMatchExpression, MaxItemsZeroAllowsEmptyArrays) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 0)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 0); ASSERT(maxItems.matchesBSON(BSON("a" << BSONArray()))); } TEST(InternalSchemaMaxItemsMatchExpression, NullArrayEntriesCountAsItems) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 2)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 2); ASSERT(maxItems.matchesBSON(BSON("a" << BSON_ARRAY(BSONNULL << 1)))); ASSERT(!maxItems.matchesBSON(BSON("a" << BSON_ARRAY(BSONNULL << 1 << 2)))); } TEST(InternalSchemaMaxItemsMatchExpression, NestedArraysAreNotUnwound) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a", 2)); + InternalSchemaMaxItemsMatchExpression maxItems("a", 2); ASSERT(maxItems.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(1 << 2 << 3))))); } TEST(InternalSchemaMaxItemsMatchExpression, NestedArraysWorkWithDottedPaths) { - InternalSchemaMaxItemsMatchExpression maxItems; - ASSERT_OK(maxItems.init("a.b", 2)); + InternalSchemaMaxItemsMatchExpression maxItems("a.b", 2); ASSERT(maxItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1))))); ASSERT(!maxItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2 << 3))))); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_length.h b/src/mongo/db/matcher/schema/expression_internal_schema_max_length.h index a0e9cbad8bf..377b5b0f174 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_length.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_length.h @@ -36,9 +36,10 @@ namespace mongo { class InternalSchemaMaxLengthMatchExpression final : public InternalSchemaStrLengthMatchExpression { public: - InternalSchemaMaxLengthMatchExpression() - : InternalSchemaStrLengthMatchExpression(MatchType::INTERNAL_SCHEMA_MAX_LENGTH, - "$_internalSchemaMaxLength"_sd) {} + InternalSchemaMaxLengthMatchExpression(StringData path, long long strLen) + : InternalSchemaStrLengthMatchExpression( + MatchType::INTERNAL_SCHEMA_MAX_LENGTH, path, strLen, "$_internalSchemaMaxLength"_sd) { + } Validator getComparator() const final { return [strLen = strLen()](int lenWithoutNullTerm) { @@ -48,8 +49,7 @@ public: std::unique_ptr<MatchExpression> shallowClone() const final { std::unique_ptr<InternalSchemaMaxLengthMatchExpression> maxLen = - stdx::make_unique<InternalSchemaMaxLengthMatchExpression>(); - invariantOK(maxLen->init(path(), strLen())); + stdx::make_unique<InternalSchemaMaxLengthMatchExpression>(path(), strLen()); if (getTag()) { maxLen->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_length_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_max_length_test.cpp index 63b744fc829..55135c0c697 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_length_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_length_test.cpp @@ -38,8 +38,7 @@ namespace mongo { namespace { TEST(InternalSchemaMaxLengthMatchExpression, RejectsNonStringElements) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a", 1)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 1); ASSERT_FALSE(maxLength.matchesBSON(BSON("a" << BSONObj()))); ASSERT_FALSE(maxLength.matchesBSON(BSON("a" << 1))); @@ -47,8 +46,7 @@ TEST(InternalSchemaMaxLengthMatchExpression, RejectsNonStringElements) { } TEST(InternalSchemaMaxLengthMatchExpression, RejectsStringsWithTooManyChars) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a", 2)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 2); ASSERT_FALSE(maxLength.matchesBSON(BSON("a" << "abc"))); @@ -57,8 +55,7 @@ TEST(InternalSchemaMaxLengthMatchExpression, RejectsStringsWithTooManyChars) { } TEST(InternalSchemaMaxLengthMatchExpression, AcceptsStringsWithLessThanOrEqualToMax) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a", 2)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 2); ASSERT_TRUE(maxLength.matchesBSON(BSON("a" << "ab"))); @@ -69,26 +66,21 @@ TEST(InternalSchemaMaxLengthMatchExpression, AcceptsStringsWithLessThanOrEqualTo } TEST(InternalSchemaMaxLengthMatchExpression, MaxLengthZeroAllowsEmptyString) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a", 0)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 0); ASSERT_TRUE(maxLength.matchesBSON(BSON("a" << ""))); } TEST(InternalSchemaMaxLengthMatchExpression, RejectsNull) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a", 1)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 1); ASSERT_FALSE(maxLength.matchesBSON(BSON("a" << BSONNULL))); } TEST(InternalSchemaMaxLengthMatchExpression, TreatsMultiByteCodepointAsOneCharacter) { - InternalSchemaMaxLengthMatchExpression nonMatchingMaxLength; - InternalSchemaMaxLengthMatchExpression matchingMaxLength; - - ASSERT_OK(nonMatchingMaxLength.init("a", 0)); - ASSERT_OK(matchingMaxLength.init("a", 1)); + InternalSchemaMaxLengthMatchExpression nonMatchingMaxLength("a", 0); + InternalSchemaMaxLengthMatchExpression matchingMaxLength("a", 1); // This string has one code point, so it should meet maximum length 1 but not maximum length 0. constexpr auto testString = u8"\U0001f4a9"; @@ -97,11 +89,8 @@ TEST(InternalSchemaMaxLengthMatchExpression, TreatsMultiByteCodepointAsOneCharac } TEST(InternalSchemaMaxLengthMatchExpression, CorectlyCountsUnicodeCodepoints) { - InternalSchemaMaxLengthMatchExpression nonMatchingMaxLength; - InternalSchemaMaxLengthMatchExpression matchingMaxLength; - - ASSERT_OK(nonMatchingMaxLength.init("a", 4)); - ASSERT_OK(matchingMaxLength.init("a", 5)); + InternalSchemaMaxLengthMatchExpression nonMatchingMaxLength("a", 4); + InternalSchemaMaxLengthMatchExpression matchingMaxLength("a", 5); // A test string that contains single-byte, 2-byte, 3-byte, and 4-byte codepoints. constexpr auto testString = @@ -118,9 +107,7 @@ TEST(InternalSchemaMaxLengthMatchExpression, CorectlyCountsUnicodeCodepoints) { } TEST(InternalSchemaMaxLengthMatchExpression, DealsWithInvalidUTF8) { - InternalSchemaMaxLengthMatchExpression maxLength; - - ASSERT_OK(maxLength.init("a", 1)); + InternalSchemaMaxLengthMatchExpression maxLength("a", 1); // Several kinds of invalid byte sequences listed in the Wikipedia article about UTF-8: // https://en.wikipedia.org/wiki/UTF-8 @@ -138,8 +125,7 @@ TEST(InternalSchemaMaxLengthMatchExpression, DealsWithInvalidUTF8) { } TEST(InternalSchemaMaxLengthMatchExpression, NestedArraysWorkWithDottedPaths) { - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(maxLength.init("a.b", 2)); + InternalSchemaMaxLengthMatchExpression maxLength("a.b", 2); ASSERT_TRUE(maxLength.matchesBSON(BSON("a" << BSON("b" << "a")))); @@ -150,22 +136,17 @@ TEST(InternalSchemaMaxLengthMatchExpression, NestedArraysWorkWithDottedPaths) { } TEST(InternalSchemaMaxLengthMatchExpression, SameMaxLengthTreatedEquivalent) { - InternalSchemaMaxLengthMatchExpression maxLength1; - InternalSchemaMaxLengthMatchExpression maxLength2; - InternalSchemaMaxLengthMatchExpression maxLength3; - ASSERT_OK(maxLength1.init("a", 2)); - ASSERT_OK(maxLength2.init("a", 2)); - ASSERT_OK(maxLength3.init("a", 3)); + InternalSchemaMaxLengthMatchExpression maxLength1("a", 2); + InternalSchemaMaxLengthMatchExpression maxLength2("a", 2); + InternalSchemaMaxLengthMatchExpression maxLength3("a", 3); ASSERT_TRUE(maxLength1.equivalent(&maxLength2)); ASSERT_FALSE(maxLength1.equivalent(&maxLength3)); } TEST(InternalSchemaMaxLengthMatchExpression, MinLengthAndMaxLengthAreNotEquivalent) { - InternalSchemaMinLengthMatchExpression minLength; - InternalSchemaMaxLengthMatchExpression maxLength; - ASSERT_OK(minLength.init("a", 2)); - ASSERT_OK(maxLength.init("a", 2)); + InternalSchemaMinLengthMatchExpression minLength("a", 2); + InternalSchemaMaxLengthMatchExpression maxLength("a", 2); ASSERT_FALSE(maxLength.equivalent(&minLength)); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties.h index 5736ca08017..82bc65dabef 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties.h @@ -39,8 +39,9 @@ namespace mongo { class InternalSchemaMaxPropertiesMatchExpression final : public InternalSchemaNumPropertiesMatchExpression { public: - InternalSchemaMaxPropertiesMatchExpression() + explicit InternalSchemaMaxPropertiesMatchExpression(long long numProperties) : InternalSchemaNumPropertiesMatchExpression(MatchType::INTERNAL_SCHEMA_MAX_PROPERTIES, + numProperties, "$_internalSchemaMaxProperties") {} bool matches(const MatchableDocument* doc, MatchDetails* details) const final { @@ -57,8 +58,8 @@ public: } virtual std::unique_ptr<MatchExpression> shallowClone() const final { - auto maxProperties = stdx::make_unique<InternalSchemaMaxPropertiesMatchExpression>(); - invariantOK(maxProperties->init(numProperties())); + auto maxProperties = + stdx::make_unique<InternalSchemaMaxPropertiesMatchExpression>(numProperties()); if (getTag()) { maxProperties->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp index c626bd81844..16c1c4f1fac 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_max_properties_test.cpp @@ -38,16 +38,14 @@ namespace mongo { namespace { TEST(InternalSchemaMaxPropertiesMatchExpression, RejectsObjectsWithTooManyElements) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - ASSERT_OK(maxProperties.init(0)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(0); ASSERT_FALSE(maxProperties.matchesBSON(BSON("b" << 21))); ASSERT_FALSE(maxProperties.matchesBSON(BSON("b" << 21 << "c" << 3))); } TEST(InternalSchemaMaxPropertiesMatchExpression, AcceptsObjectWithLessThanOrEqualToMaxElements) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - ASSERT_OK(maxProperties.init(2)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(2); ASSERT_TRUE(maxProperties.matchesBSON(BSONObj())); ASSERT_TRUE(maxProperties.matchesBSON(BSON("b" << BSONNULL))); @@ -56,26 +54,21 @@ TEST(InternalSchemaMaxPropertiesMatchExpression, AcceptsObjectWithLessThanOrEqua } TEST(InternalSchemaMaxPropertiesMatchExpression, MaxPropertiesZeroAllowsEmptyObjects) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - ASSERT_OK(maxProperties.init(0)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(0); ASSERT_TRUE(maxProperties.matchesBSON(BSONObj())); } TEST(InternalSchemaMaxPropertiesMatchExpression, NestedObjectsAreNotUnwound) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - ASSERT_OK(maxProperties.init(1)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(1); ASSERT_TRUE(maxProperties.matchesBSON(BSON("b" << BSON("c" << 2 << "d" << 3)))); } TEST(InternalSchemaMaxPropertiesMatchExpression, EquivalentFunctionIsAccurate) { - InternalSchemaMaxPropertiesMatchExpression maxProperties1; - InternalSchemaMaxPropertiesMatchExpression maxProperties2; - InternalSchemaMaxPropertiesMatchExpression maxProperties3; - ASSERT_OK(maxProperties1.init(1)); - ASSERT_OK(maxProperties2.init(1)); - ASSERT_OK(maxProperties3.init(2)); + InternalSchemaMaxPropertiesMatchExpression maxProperties1(1); + InternalSchemaMaxPropertiesMatchExpression maxProperties2(1); + InternalSchemaMaxPropertiesMatchExpression maxProperties3(2); ASSERT_TRUE(maxProperties1.equivalent(&maxProperties1)); ASSERT_TRUE(maxProperties1.equivalent(&maxProperties2)); @@ -83,17 +76,14 @@ TEST(InternalSchemaMaxPropertiesMatchExpression, EquivalentFunctionIsAccurate) { } TEST(InternalSchemaMaxPropertiesMatchExpression, NestedArraysAreNotUnwound) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - ASSERT_OK(maxProperties.init(2)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(2); ASSERT_TRUE(maxProperties.matchesBSON(BSON("a" << (BSON("b" << 2 << "c" << 3 << "d" << 4))))); } TEST(InternalSchemaMaxPropertiesMatchExpression, MinPropertiesNotEquivalentToMaxProperties) { - InternalSchemaMaxPropertiesMatchExpression maxProperties; - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(maxProperties.init(5)); - ASSERT_OK(minProperties.init(5)); + InternalSchemaMaxPropertiesMatchExpression maxProperties(5); + InternalSchemaMinPropertiesMatchExpression minProperties(5); ASSERT_FALSE(maxProperties.equivalent(&minProperties)); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_min_items.h index 82eb16b5511..3aaffb62347 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_items.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_items.h @@ -39,9 +39,9 @@ namespace mongo { class InternalSchemaMinItemsMatchExpression final : public InternalSchemaNumArrayItemsMatchExpression { public: - InternalSchemaMinItemsMatchExpression() - : InternalSchemaNumArrayItemsMatchExpression(INTERNAL_SCHEMA_MIN_ITEMS, - "$_internalSchemaMinItems"_sd) {} + InternalSchemaMinItemsMatchExpression(StringData path, long long numItems) + : InternalSchemaNumArrayItemsMatchExpression( + INTERNAL_SCHEMA_MIN_ITEMS, path, numItems, "$_internalSchemaMinItems"_sd) {} bool matchesArray(const BSONObj& anArray, MatchDetails* details) const final { return (anArray.nFields() >= numItems()); @@ -49,8 +49,7 @@ public: std::unique_ptr<MatchExpression> shallowClone() const final { std::unique_ptr<InternalSchemaMinItemsMatchExpression> minItems = - stdx::make_unique<InternalSchemaMinItemsMatchExpression>(); - invariantOK(minItems->init(path(), numItems())); + stdx::make_unique<InternalSchemaMinItemsMatchExpression>(path(), numItems()); if (getTag()) { minItems->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp index 2f43c269c7f..1df2e453539 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_items_test.cpp @@ -36,8 +36,7 @@ namespace mongo { namespace { TEST(InternalSchemaMinItemsMatchExpression, RejectsNonArrayElements) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 1)); + InternalSchemaMinItemsMatchExpression minItems("a", 1); ASSERT(!minItems.matchesBSON(BSON("a" << BSONObj()))); ASSERT(!minItems.matchesBSON(BSON("a" << 1))); @@ -46,46 +45,40 @@ TEST(InternalSchemaMinItemsMatchExpression, RejectsNonArrayElements) { } TEST(InternalSchemaMinItemsMatchExpression, RejectsArraysWithTooFewElements) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 2)); + InternalSchemaMinItemsMatchExpression minItems("a", 2); ASSERT(!minItems.matchesBSON(BSON("a" << BSONArray()))); ASSERT(!minItems.matchesBSON(BSON("a" << BSON_ARRAY(1)))); } TEST(InternalSchemaMinItemsMatchExpression, AcceptsArrayWithAtLeastMinElements) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 2)); + InternalSchemaMinItemsMatchExpression minItems("a", 2); ASSERT(minItems.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2)))); ASSERT(minItems.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3)))); } TEST(InternalSchemaMinItemsMatchExpression, MinItemsZeroAllowsEmptyArrays) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 0)); + InternalSchemaMinItemsMatchExpression minItems("a", 0); ASSERT(minItems.matchesBSON(BSON("a" << BSONArray()))); } TEST(InternalSchemaMinItemsMatchExpression, NullArrayEntriesCountAsItems) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 1)); + InternalSchemaMinItemsMatchExpression minItems("a", 1); ASSERT(minItems.matchesBSON(BSON("a" << BSON_ARRAY(BSONNULL)))); ASSERT(minItems.matchesBSON(BSON("a" << BSON_ARRAY(BSONNULL << 1)))); } TEST(InternalSchemaMinItemsMatchExpression, NestedArraysAreNotUnwound) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a", 2)); + InternalSchemaMinItemsMatchExpression minItems("a", 2); ASSERT(!minItems.matchesBSON(BSON("a" << BSON_ARRAY(BSON_ARRAY(1 << 2))))); } TEST(InternalSchemaMinItemsMatchExpression, NestedArraysWorkWithDottedPaths) { - InternalSchemaMinItemsMatchExpression minItems; - ASSERT_OK(minItems.init("a.b", 2)); + InternalSchemaMinItemsMatchExpression minItems("a.b", 2); ASSERT(minItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1 << 2))))); ASSERT(!minItems.matchesBSON(BSON("a" << BSON("b" << BSON_ARRAY(1))))); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_length.h b/src/mongo/db/matcher/schema/expression_internal_schema_min_length.h index 1d4d18da4e2..aad59831247 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_length.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_length.h @@ -36,9 +36,10 @@ namespace mongo { class InternalSchemaMinLengthMatchExpression final : public InternalSchemaStrLengthMatchExpression { public: - InternalSchemaMinLengthMatchExpression() - : InternalSchemaStrLengthMatchExpression(MatchType::INTERNAL_SCHEMA_MIN_LENGTH, - "$_internalSchemaMinLength"_sd) {} + InternalSchemaMinLengthMatchExpression(StringData path, long long strLen) + : InternalSchemaStrLengthMatchExpression( + MatchType::INTERNAL_SCHEMA_MIN_LENGTH, path, strLen, "$_internalSchemaMinLength"_sd) { + } Validator getComparator() const final { return [strLen = strLen()](int lenWithoutNullTerm) { @@ -48,8 +49,7 @@ public: std::unique_ptr<MatchExpression> shallowClone() const final { std::unique_ptr<InternalSchemaMinLengthMatchExpression> minLen = - stdx::make_unique<InternalSchemaMinLengthMatchExpression>(); - invariantOK(minLen->init(path(), strLen())); + stdx::make_unique<InternalSchemaMinLengthMatchExpression>(path(), strLen()); if (getTag()) { minLen->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_length_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_min_length_test.cpp index 2e72f8ea2ac..8fbdd695d0b 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_length_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_length_test.cpp @@ -37,8 +37,7 @@ namespace mongo { namespace { TEST(InternalSchemaMinLengthMatchExpression, RejectsNonStringElements) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a", 1)); + InternalSchemaMinLengthMatchExpression minLength("a", 1); ASSERT_FALSE(minLength.matchesBSON(BSON("a" << BSONObj()))); ASSERT_FALSE(minLength.matchesBSON(BSON("a" << 1))); @@ -46,8 +45,7 @@ TEST(InternalSchemaMinLengthMatchExpression, RejectsNonStringElements) { } TEST(InternalSchemaMinLengthMatchExpression, RejectsStringsWithTooFewChars) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a", 2)); + InternalSchemaMinLengthMatchExpression minLength("a", 2); ASSERT_FALSE(minLength.matchesBSON(BSON("a" << ""))); @@ -56,8 +54,7 @@ TEST(InternalSchemaMinLengthMatchExpression, RejectsStringsWithTooFewChars) { } TEST(InternalSchemaMinLengthMatchExpression, AcceptsStringWithAtLeastMinChars) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a", 2)); + InternalSchemaMinLengthMatchExpression minLength("a", 2); ASSERT_TRUE(minLength.matchesBSON(BSON("a" << "ab"))); @@ -68,26 +65,21 @@ TEST(InternalSchemaMinLengthMatchExpression, AcceptsStringWithAtLeastMinChars) { } TEST(InternalSchemaMinLengthMatchExpression, MinLengthZeroAllowsEmptyString) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a", 0)); + InternalSchemaMinLengthMatchExpression minLength("a", 0); ASSERT_TRUE(minLength.matchesBSON(BSON("a" << ""))); } TEST(InternalSchemaMinLengthMatchExpression, RejectsNull) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a", 1)); + InternalSchemaMinLengthMatchExpression minLength("a", 1); ASSERT_FALSE(minLength.matchesBSON(BSON("a" << BSONNULL))); } TEST(InternalSchemaMinLengthMatchExpression, TreatsMultiByteCodepointAsOneCharacter) { - InternalSchemaMinLengthMatchExpression matchingMinLength; - InternalSchemaMinLengthMatchExpression nonMatchingMinLength; - - ASSERT_OK(matchingMinLength.init("a", 1)); - ASSERT_OK(nonMatchingMinLength.init("a", 2)); + InternalSchemaMinLengthMatchExpression matchingMinLength("a", 1); + InternalSchemaMinLengthMatchExpression nonMatchingMinLength("a", 2); // This string has one code point, so it should meet minimum length 1 but not minimum length 2. constexpr auto testString = u8"\U0001f4a9"; @@ -96,11 +88,8 @@ TEST(InternalSchemaMinLengthMatchExpression, TreatsMultiByteCodepointAsOneCharac } TEST(InternalSchemaMinLengthMatchExpression, CorectlyCountsUnicodeCodepoints) { - InternalSchemaMinLengthMatchExpression matchingMinLength; - InternalSchemaMinLengthMatchExpression nonMatchingMinLength; - - ASSERT_OK(matchingMinLength.init("a", 5)); - ASSERT_OK(nonMatchingMinLength.init("a", 6)); + InternalSchemaMinLengthMatchExpression matchingMinLength("a", 5); + InternalSchemaMinLengthMatchExpression nonMatchingMinLength("a", 6); // A test string that contains single-byte, 2-byte, 3-byte, and 4-byte code points. constexpr auto testString = @@ -117,9 +106,7 @@ TEST(InternalSchemaMinLengthMatchExpression, CorectlyCountsUnicodeCodepoints) { } TEST(InternalSchemaMinLengthMatchExpression, DealsWithInvalidUTF8) { - InternalSchemaMinLengthMatchExpression minLength; - - ASSERT_OK(minLength.init("a", 1)); + InternalSchemaMinLengthMatchExpression minLength("a", 1); // Several kinds of invalid byte sequences listed in the Wikipedia article about UTF-8: // https://en.wikipedia.org/wiki/UTF-8 @@ -137,8 +124,7 @@ TEST(InternalSchemaMinLengthMatchExpression, DealsWithInvalidUTF8) { } TEST(InternalSchemaMinLengthMatchExpression, NestedFieldsWorkWithDottedPaths) { - InternalSchemaMinLengthMatchExpression minLength; - ASSERT_OK(minLength.init("a.b", 2)); + InternalSchemaMinLengthMatchExpression minLength("a.b", 2); ASSERT_TRUE(minLength.matchesBSON(BSON("a" << BSON("b" << "ab")))); @@ -149,12 +135,9 @@ TEST(InternalSchemaMinLengthMatchExpression, NestedFieldsWorkWithDottedPaths) { } TEST(InternalSchemaMinLengthMatchExpression, SameMinLengthTreatedEquivalent) { - InternalSchemaMinLengthMatchExpression minLength1; - InternalSchemaMinLengthMatchExpression minLength2; - InternalSchemaMinLengthMatchExpression minLength3; - ASSERT_OK(minLength1.init("a", 2)); - ASSERT_OK(minLength2.init("a", 2)); - ASSERT_OK(minLength3.init("a", 3)); + InternalSchemaMinLengthMatchExpression minLength1("a", 2); + InternalSchemaMinLengthMatchExpression minLength2("a", 2); + InternalSchemaMinLengthMatchExpression minLength3("a", 3); ASSERT_TRUE(minLength1.equivalent(&minLength2)); ASSERT_FALSE(minLength1.equivalent(&minLength3)); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties.h index b97506fd882..9ac68da48a3 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties.h @@ -39,8 +39,9 @@ namespace mongo { class InternalSchemaMinPropertiesMatchExpression final : public InternalSchemaNumPropertiesMatchExpression { public: - InternalSchemaMinPropertiesMatchExpression() + explicit InternalSchemaMinPropertiesMatchExpression(long long numProperties) : InternalSchemaNumPropertiesMatchExpression(MatchType::INTERNAL_SCHEMA_MIN_PROPERTIES, + numProperties, "$_internalSchemaMinProperties") {} bool matches(const MatchableDocument* doc, MatchDetails* details) const final { @@ -57,8 +58,8 @@ public: } virtual std::unique_ptr<MatchExpression> shallowClone() const final { - auto minProperties = stdx::make_unique<InternalSchemaMinPropertiesMatchExpression>(); - invariantOK(minProperties->init(numProperties())); + auto minProperties = + stdx::make_unique<InternalSchemaMinPropertiesMatchExpression>(numProperties()); if (getTag()) { minProperties->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp index e364180a7f9..1699c2a6fd4 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_min_properties_test.cpp @@ -38,16 +38,14 @@ namespace mongo { namespace { TEST(InternalSchemaMinPropertiesMatchExpression, RejectsObjectsWithTooFewElements) { - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(minProperties.init(2)); + InternalSchemaMinPropertiesMatchExpression minProperties(2); ASSERT_FALSE(minProperties.matchesBSON(BSONObj())); ASSERT_FALSE(minProperties.matchesBSON(BSON("b" << 21))); } TEST(InternalSchemaMinPropertiesMatchExpression, AcceptsObjectWithAtLeastMinElements) { - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(minProperties.init(2)); + InternalSchemaMinPropertiesMatchExpression minProperties(2); ASSERT_TRUE(minProperties.matchesBSON(BSON("b" << 21 << "c" << BSONNULL))); ASSERT_TRUE(minProperties.matchesBSON(BSON("b" << 21 << "c" << 3))); @@ -55,33 +53,27 @@ TEST(InternalSchemaMinPropertiesMatchExpression, AcceptsObjectWithAtLeastMinElem } TEST(InternalSchemaMinPropertiesMatchExpression, MinPropertiesZeroAllowsEmptyObjects) { - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(minProperties.init(0)); + InternalSchemaMinPropertiesMatchExpression minProperties(0); ASSERT_TRUE(minProperties.matchesBSON(BSONObj())); } TEST(InternalSchemaMinPropertiesMatchExpression, NestedObjectsAreNotUnwound) { - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(minProperties.init(2)); + InternalSchemaMinPropertiesMatchExpression minProperties(2); ASSERT_FALSE(minProperties.matchesBSON(BSON("b" << BSON("c" << 2 << "d" << 3)))); } TEST(InternalSchemaMinPropertiesMatchExpression, NestedArraysAreNotUnwound) { - InternalSchemaMinPropertiesMatchExpression minProperties; - ASSERT_OK(minProperties.init(2)); + InternalSchemaMinPropertiesMatchExpression minProperties(2); ASSERT_FALSE(minProperties.matchesBSON(BSON("a" << (BSON("b" << 2 << "c" << 3 << "d" << 4))))); } TEST(InternalSchemaMinPropertiesMatchExpression, EquivalentFunctionIsAccurate) { - InternalSchemaMinPropertiesMatchExpression minProperties1; - InternalSchemaMinPropertiesMatchExpression minProperties2; - InternalSchemaMinPropertiesMatchExpression minProperties3; - ASSERT_OK(minProperties1.init(1)); - ASSERT_OK(minProperties2.init(1)); - ASSERT_OK(minProperties3.init(2)); + InternalSchemaMinPropertiesMatchExpression minProperties1(1); + InternalSchemaMinPropertiesMatchExpression minProperties2(1); + InternalSchemaMinPropertiesMatchExpression minProperties3(2); ASSERT_TRUE(minProperties1.equivalent(&minProperties1)); ASSERT_TRUE(minProperties1.equivalent(&minProperties2)); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.cpp index f6a31657847..d5bc5069a35 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.cpp @@ -32,6 +32,10 @@ namespace mongo { +InternalSchemaNumArrayItemsMatchExpression::InternalSchemaNumArrayItemsMatchExpression( + MatchType type, StringData path, long long numItems, StringData name) + : ArrayMatchingMatchExpression(type, path), _name(name), _numItems(numItems) {} + void InternalSchemaNumArrayItemsMatchExpression::debugString(StringBuilder& debug, int level) const { _debugAddSpace(debug, level); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h index 05dd873d772..b8db5a34258 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_num_array_items.h @@ -38,16 +38,13 @@ namespace mongo { */ class InternalSchemaNumArrayItemsMatchExpression : public ArrayMatchingMatchExpression { public: - InternalSchemaNumArrayItemsMatchExpression(MatchType type, StringData name) - : ArrayMatchingMatchExpression(type), _name(name) {} + InternalSchemaNumArrayItemsMatchExpression(MatchType type, + StringData path, + long long numItems, + StringData name); virtual ~InternalSchemaNumArrayItemsMatchExpression() {} - Status init(StringData path, long long numItems) { - _numItems = numItems; - return setPath(path); - } - void debugString(StringBuilder& debug, int level) const final; void serialize(BSONObjBuilder* out) const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h b/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h index ced6529a668..541b30ebfe4 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_num_properties.h @@ -39,16 +39,13 @@ namespace mongo { */ class InternalSchemaNumPropertiesMatchExpression : public MatchExpression { public: - InternalSchemaNumPropertiesMatchExpression(MatchType type, std::string name) - : MatchExpression(type), _name(name) {} + InternalSchemaNumPropertiesMatchExpression(MatchType type, + long long numProperties, + std::string name) + : MatchExpression(type), _numProperties(numProperties), _name(name) {} virtual ~InternalSchemaNumPropertiesMatchExpression() {} - Status init(long long numProperties) { - _numProperties = numProperties; - return Status::OK(); - } - size_t numChildren() const final { return 0; } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.cpp index 9e8d5ac702a..d6a8c05342b 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.cpp @@ -34,6 +34,12 @@ namespace mongo { constexpr StringData InternalSchemaObjectMatchExpression::kName; +InternalSchemaObjectMatchExpression::InternalSchemaObjectMatchExpression( + StringData path, std::unique_ptr<MatchExpression> expr) + : PathMatchExpression(INTERNAL_SCHEMA_OBJECT_MATCH, path), _sub(std::move(expr)) { + setTraverseLeafArray(); +} + bool InternalSchemaObjectMatchExpression::matchesSingleElement(const BSONElement& elem, MatchDetails* details) const { if (elem.type() != BSONType::Object) { @@ -65,8 +71,8 @@ bool InternalSchemaObjectMatchExpression::equivalent(const MatchExpression* othe } std::unique_ptr<MatchExpression> InternalSchemaObjectMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - invariantOK(clone->init(_sub->shallowClone(), path())); + auto clone = + stdx::make_unique<InternalSchemaObjectMatchExpression>(path(), _sub->shallowClone()); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h index ef328388c0b..776d35af6de 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match.h @@ -36,12 +36,7 @@ class InternalSchemaObjectMatchExpression final : public PathMatchExpression { public: static constexpr StringData kName = "$_internalSchemaObjectMatch"_sd; - InternalSchemaObjectMatchExpression() : PathMatchExpression(INTERNAL_SCHEMA_OBJECT_MATCH) {} - - Status init(std::unique_ptr<MatchExpression> expr, StringData path) { - _sub = std::move(expr); - return setPath(path); - } + InternalSchemaObjectMatchExpression(StringData path, std::unique_ptr<MatchExpression> expr); bool matchesSingleElement(const BSONElement& elem, MatchDetails* details = nullptr) const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp index a6d0ff5b5f9..f6ad77e4e06 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_object_match_test.cpp @@ -45,8 +45,7 @@ TEST(InternalSchemaObjectMatchExpression, RejectsNonObjectElements) { auto subExpr = MatchExpressionParser::parse(BSON("b" << 1), expCtx); ASSERT_OK(subExpr.getStatus()); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK(objMatch.init(std::move(subExpr.getValue()), "a"_sd)); + InternalSchemaObjectMatchExpression objMatch("a"_sd, std::move(subExpr.getValue())); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" << 1))); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" @@ -61,8 +60,7 @@ TEST(InternalSchemaObjectMatchExpression, RejectsObjectsThatDontMatch) { expCtx); ASSERT_OK(subExpr.getStatus()); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK(objMatch.init(std::move(subExpr.getValue()), "a"_sd)); + InternalSchemaObjectMatchExpression objMatch("a"_sd, std::move(subExpr.getValue())); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" << BSON("b" << 1)))); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" << BSON("b" << BSONObj())))); @@ -75,8 +73,7 @@ TEST(InternalSchemaObjectMatchExpression, AcceptsObjectsThatMatch) { expCtx); ASSERT_OK(subExpr.getStatus()); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK(objMatch.init(std::move(subExpr.getValue()), "a"_sd)); + InternalSchemaObjectMatchExpression objMatch("a"_sd, std::move(subExpr.getValue())); ASSERT_TRUE(objMatch.matchesBSON(BSON("a" << BSON("b" << "string")))); @@ -97,8 +94,7 @@ TEST(InternalSchemaObjectMatchExpression, DottedPathAcceptsObjectsThatMatch) { expCtx); ASSERT_OK(subExpr.getStatus()); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK(objMatch.init(std::move(subExpr.getValue()), "a"_sd)); + InternalSchemaObjectMatchExpression objMatch("a"_sd, std::move(subExpr.getValue())); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" << BSON("d" << "string")))); @@ -112,8 +108,7 @@ TEST(InternalSchemaObjectMatchExpression, EmptyMatchAcceptsAllObjects) { auto subExpr = MatchExpressionParser::parse(BSONObj(), expCtx); ASSERT_OK(subExpr.getStatus()); - InternalSchemaObjectMatchExpression objMatch; - ASSERT_OK(objMatch.init(std::move(subExpr.getValue()), "a"_sd)); + InternalSchemaObjectMatchExpression objMatch("a"_sd, std::move(subExpr.getValue())); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" << 1))); ASSERT_FALSE(objMatch.matchesBSON(BSON("a" diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.cpp index c0a5bbf8922..2684533c465 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.cpp @@ -68,8 +68,7 @@ bool InternalSchemaRootDocEqMatchExpression::equivalent(const MatchExpression* o } std::unique_ptr<MatchExpression> InternalSchemaRootDocEqMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaRootDocEqMatchExpression>(); - clone->init(_rhsObj); + auto clone = stdx::make_unique<InternalSchemaRootDocEqMatchExpression>(_rhsObj.copy()); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h index e6f53658eda..7ca66e89ca2 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq.h @@ -45,12 +45,11 @@ class InternalSchemaRootDocEqMatchExpression final : public MatchExpression { public: static constexpr StringData kName = "$_internalSchemaRootDocEq"_sd; - InternalSchemaRootDocEqMatchExpression() - : MatchExpression(MatchExpression::INTERNAL_SCHEMA_ROOT_DOC_EQ) {} - - void init(BSONObj obj) { - _rhsObj = std::move(obj); - } + /** + * Constructs a new match expression, taking ownership of 'rhs'. + */ + explicit InternalSchemaRootDocEqMatchExpression(BSONObj rhs) + : MatchExpression(MatchExpression::INTERNAL_SCHEMA_ROOT_DOC_EQ), _rhsObj(std::move(rhs)) {} bool matches(const MatchableDocument* doc, MatchDetails* details = nullptr) const final; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp index ade721236d3..0a1e36d69c2 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_root_doc_eq_test.cpp @@ -38,9 +38,8 @@ namespace mongo { namespace { TEST(InternalSchemaRootDocEqMatchExpression, MatchesObject) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSON("a" << 1 << "b" - << "string")); + InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << 1 << "b" + << "string")); ASSERT_TRUE(rootDocEq.matchesBSON(BSON("a" << 1 << "b" << "string"))); ASSERT_FALSE(rootDocEq.matchesBSON(BSON("a" << 2 << "b" @@ -48,40 +47,34 @@ TEST(InternalSchemaRootDocEqMatchExpression, MatchesObject) { } TEST(InternalSchemaRootDocEqMatchExpression, MatchesNestedObject) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSON("a" << 1 << "b" << BSON("c" << 1))); + InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << 1 << "b" << BSON("c" << 1))); ASSERT_TRUE(rootDocEq.matchesBSON(BSON("a" << 1 << "b" << BSON("c" << 1)))); ASSERT_FALSE(rootDocEq.matchesBSON(BSON("a" << 1 << "b" << BSON("c" << 2)))); } TEST(InternalSchemaRootDocEqMatchExpression, MatchesObjectIgnoresElementOrder) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSON("a" << 1 << "b" << BSON("c" << 1))); + InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << 1 << "b" << BSON("c" << 1))); ASSERT_TRUE(rootDocEq.matchesBSON(BSON("b" << BSON("c" << 1) << "a" << 1))); } TEST(InternalSchemaRootDocEqMatchExpression, MatchesNestedObjectIgnoresElementOrder) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSON("a" << BSON("b" << 1 << "c" << 1))); + InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << BSON("b" << 1 << "c" << 1))); ASSERT_TRUE(rootDocEq.matchesBSON(BSON("a" << BSON("c" << 1 << "b" << 1)))); } TEST(InternalSchemaRootDocEqMatchExpression, MatchesEmptyObject) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSONObj()); + InternalSchemaRootDocEqMatchExpression rootDocEq{BSONObj()}; ASSERT_TRUE(rootDocEq.matchesBSON(BSONObj())); } TEST(InternalSchemaRootDocEqMatchExpression, MatchesNestedArray) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(BSON("a" << BSON_ARRAY(1 << 2 << 3))); + InternalSchemaRootDocEqMatchExpression rootDocEq(BSON("a" << BSON_ARRAY(1 << 2 << 3))); ASSERT_TRUE(rootDocEq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 2 << 3)))); ASSERT_FALSE(rootDocEq.matchesBSON(BSON("a" << BSON_ARRAY(1 << 3 << 2)))); } TEST(InternalSchemaRootDocEqMatchExpression, MatchesObjectWithNullElement) { - InternalSchemaRootDocEqMatchExpression rootDocEq; - rootDocEq.init(fromjson("{a: null}")); + InternalSchemaRootDocEqMatchExpression rootDocEq(fromjson("{a: null}")); ASSERT_TRUE(rootDocEq.matchesBSON(fromjson("{a: null}"))); ASSERT_FALSE(rootDocEq.matchesBSON(fromjson("{a: 1}"))); ASSERT_FALSE(rootDocEq.matchesBSON(fromjson("{}"))); @@ -94,27 +87,28 @@ TEST(InternalSchemaRootDocEqMatchExpression, EquivalentReturnsCorrectResults) { b: 1, c: 1 }})"); boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - Matcher rootDocEq(query, expCtx); + Matcher rootDocEq(std::move(query), expCtx); query = fromjson(R"( {$_internalSchemaRootDocEq: { c: 1, b: 1 }})"); - Matcher exprEq(query, expCtx); + Matcher exprEq(std::move(query), expCtx); ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(exprEq.getMatchExpression())); query = fromjson(R"( {$_internalSchemaRootDocEq: { c: 1 }})"); - Matcher exprNotEq(query, expCtx); + Matcher exprNotEq(std::move(query), expCtx); ASSERT_FALSE(rootDocEq.getMatchExpression()->equivalent(exprNotEq.getMatchExpression())); } TEST(InternalSchemaRootDocEqMatchExpression, EquivalentToClone) { auto query = fromjson("{$_internalSchemaRootDocEq: {a:1, b: {c: 1, d: [1]}}}"); boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - Matcher rootDocEq(query, expCtx); + Matcher rootDocEq(std::move(query), expCtx); + auto clone = rootDocEq.getMatchExpression()->shallowClone(); ASSERT_TRUE(rootDocEq.getMatchExpression()->equivalent(clone.get())); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_str_length.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_str_length.cpp index 02a7b8895e8..f01f3e80ba5 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_str_length.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_str_length.cpp @@ -34,6 +34,12 @@ namespace mongo { +InternalSchemaStrLengthMatchExpression::InternalSchemaStrLengthMatchExpression(MatchType type, + StringData path, + long long strLen, + StringData name) + : LeafMatchExpression(type, path), _name(name), _strLen(strLen) {} + void InternalSchemaStrLengthMatchExpression::debugString(StringBuilder& debug, int level) const { _debugAddSpace(debug, level); debug << path() << " " << _name << " " << _strLen << "\n"; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_str_length.h b/src/mongo/db/matcher/schema/expression_internal_schema_str_length.h index 90830577432..2a00de506b9 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_str_length.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_str_length.h @@ -38,16 +38,13 @@ class InternalSchemaStrLengthMatchExpression : public LeafMatchExpression { public: using Validator = stdx::function<bool(int)>; - InternalSchemaStrLengthMatchExpression(MatchType type, StringData name) - : LeafMatchExpression(type), _name(name) {} + InternalSchemaStrLengthMatchExpression(MatchType type, + StringData path, + long long strLen, + StringData name); virtual ~InternalSchemaStrLengthMatchExpression() {} - Status init(StringData path, long long strLen) { - _strLen = strLen; - return setPath(path); - } - virtual Validator getComparator() const = 0; bool matchesSingleElement(const BSONElement& elem, diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.cpp index f35d14eb69b..bce1089077c 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.cpp @@ -64,8 +64,7 @@ void InternalSchemaUniqueItemsMatchExpression::serialize(BSONObjBuilder* builder } std::unique_ptr<MatchExpression> InternalSchemaUniqueItemsMatchExpression::shallowClone() const { - auto clone = stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(); - invariantOK(clone->init(path())); + auto clone = stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(path()); if (getTag()) { clone->setTag(getTag()->clone()); } diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h index f41b9e0ef34..5338d3fbcc6 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h +++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items.h @@ -45,12 +45,8 @@ class InternalSchemaUniqueItemsMatchExpression final : public ArrayMatchingMatch public: static constexpr StringData kName = "$_internalSchemaUniqueItems"_sd; - InternalSchemaUniqueItemsMatchExpression() - : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_UNIQUE_ITEMS) {} - - Status init(StringData path) { - return setPath(path); - } + explicit InternalSchemaUniqueItemsMatchExpression(StringData path) + : ArrayMatchingMatchExpression(MatchExpression::INTERNAL_SCHEMA_UNIQUE_ITEMS, path) {} size_t numChildren() const final { return 0; diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp index 5e9d1a119b4..46e3be31d41 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_unique_items_test.cpp @@ -36,8 +36,7 @@ namespace mongo { namespace { TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNonArrays) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_FALSE(uniqueItems.matchesBSON(BSON("foo" << 1))); ASSERT_FALSE(uniqueItems.matchesBSON(BSON("foo" << BSONObj()))); ASSERT_FALSE(uniqueItems.matchesBSON(BSON("foo" @@ -45,22 +44,19 @@ TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNonArrays) { } TEST(InternalSchemaUniqueItemsMatchExpression, MatchesEmptyArray) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_TRUE(uniqueItems.matchesBSON(BSON("foo" << BSONArray()))); } TEST(InternalSchemaUniqueItemsMatchExpression, MatchesOneElementArray) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_TRUE(uniqueItems.matchesBSON(BSON("foo" << BSON_ARRAY(1)))); ASSERT_TRUE(uniqueItems.matchesBSON(BSON("foo" << BSON_ARRAY(BSONObj())))); ASSERT_TRUE(uniqueItems.matchesBSON(BSON("foo" << BSON_ARRAY(BSON_ARRAY(9 << "bar"))))); } TEST(InternalSchemaUniqueItemsMatchExpression, MatchesArrayOfUniqueItems) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [1, 'bar', {}, [], null]}"))); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [{x: 1}, {x: 2}, {x: 2, y: 3}]}"))); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [[1], [1, 2], 1]}"))); @@ -68,8 +64,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, MatchesArrayOfUniqueItems) { } TEST(InternalSchemaUniqueItemsMatchExpression, MatchesNestedArrayOfUniqueItems) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo.bar")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo.bar"); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [1, 'bar', {}, [], null]}}"))); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [{x: 1}, {x: 2}, {x: 2, y: 3}]}}"))); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [[1], [1, 2], 1]}}"))); @@ -77,8 +72,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, MatchesNestedArrayOfUniqueItems) } TEST(InternalSchemaUniqueItemsMatchExpression, RejectsArrayWithDuplicates) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: [1, 1, 1]}"))); ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: [['bar'], ['bar']]}"))); ASSERT_FALSE( @@ -86,8 +80,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, RejectsArrayWithDuplicates) { } TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNestedArrayWithDuplicates) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [1, 1, 1]}}"))); ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: {bar: [['baz'], ['baz']]}}"))); ASSERT_FALSE(uniqueItems.matchesBSON( @@ -95,8 +88,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, RejectsNestedArrayWithDuplicates) } TEST(InternalSchemaUniqueItemsMatchExpression, FieldNameSignificantWhenComparingNestedObjects) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [{x: 7}, {y: 7}]}"))); ASSERT_TRUE(uniqueItems.matchesBSON(fromjson("{foo: [{a: 'bar'}, {b: 'bar'}]}"))); ASSERT_FALSE(uniqueItems.matchesBSON(fromjson("{foo: [{a: 'bar'}, {a: 'bar'}]}"))); @@ -104,8 +96,7 @@ TEST(InternalSchemaUniqueItemsMatchExpression, FieldNameSignificantWhenComparing } TEST(InternalSchemaUniqueItemsMatchExpression, AlwaysUsesBinaryComparisonRegardlessOfCollator) { - InternalSchemaUniqueItemsMatchExpression uniqueItems; - ASSERT_OK(uniqueItems.init("foo")); + InternalSchemaUniqueItemsMatchExpression uniqueItems("foo"); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); uniqueItems.setCollator(&collator); diff --git a/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp b/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp index 60d7e4d90e8..0a982bfdba1 100644 --- a/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp +++ b/src/mongo/db/matcher/schema/expression_internal_schema_xor_test.cpp @@ -99,10 +99,8 @@ TEST(InternalSchemaXorOp, DoesNotUseElemMatchKey) { TEST(InternalSchemaXorOp, Equivalent) { BSONObj baseOperand1 = BSON("a" << 1); BSONObj baseOperand2 = BSON("b" << 2); - EqualityMatchExpression sub1; - ASSERT(sub1.init("a", baseOperand1["a"]).isOK()); - EqualityMatchExpression sub2; - ASSERT(sub2.init("b", baseOperand2["b"]).isOK()); + EqualityMatchExpression sub1("a", baseOperand1["a"]); + EqualityMatchExpression sub2("b", baseOperand2["b"]); InternalSchemaXorMatchExpression e1; e1.add(sub1.shallowClone().release()); diff --git a/src/mongo/db/matcher/schema/json_schema_parser.cpp b/src/mongo/db/matcher/schema/json_schema_parser.cpp index 8c107f0b759..fc1eedcc612 100644 --- a/src/mongo/db/matcher/schema/json_schema_parser.cpp +++ b/src/mongo/db/matcher/schema/json_schema_parser.cpp @@ -160,11 +160,9 @@ std::unique_ptr<MatchExpression> makeRestriction(const MatcherTypeSet& restricti // // We need to do this because restriction keywords do not apply when a field is either not // present or of a different type. - auto typeExpr = stdx::make_unique<InternalSchemaTypeExpression>(); - invariantOK(typeExpr->init(path, restrictionType)); + auto typeExpr = stdx::make_unique<InternalSchemaTypeExpression>(path, restrictionType); - auto notExpr = stdx::make_unique<NotMatchExpression>(); - invariantOK(notExpr->init(typeExpr.release())); + auto notExpr = stdx::make_unique<NotMatchExpression>(typeExpr.release()); auto orExpr = stdx::make_unique<OrMatchExpression>(); orExpr->add(notExpr.release()); @@ -228,11 +226,8 @@ StatusWith<std::unique_ptr<InternalSchemaTypeExpression>> parseType( << "' must name at least one type")}; } - auto typeExpr = stdx::make_unique<InternalSchemaTypeExpression>(); - auto initStatus = typeExpr->init(path, std::move(typeSet.getValue())); - if (!initStatus.isOK()) { - return initStatus; - } + auto typeExpr = + stdx::make_unique<InternalSchemaTypeExpression>(path, std::move(typeSet.getValue())); return {std::move(typeExpr)}; } @@ -254,13 +249,9 @@ StatusWithMatchExpression parseMaximum(StringData path, std::unique_ptr<ComparisonMatchExpression> expr; if (isExclusiveMaximum) { - expr = stdx::make_unique<LTMatchExpression>(); + expr = stdx::make_unique<LTMatchExpression>(path, maximum); } else { - expr = stdx::make_unique<LTEMatchExpression>(); - } - auto status = expr->init(path, maximum); - if (!status.isOK()) { - return status; + expr = stdx::make_unique<LTEMatchExpression>(path, maximum); } MatcherTypeSet restrictionType; @@ -285,13 +276,9 @@ StatusWithMatchExpression parseMinimum(StringData path, std::unique_ptr<ComparisonMatchExpression> expr; if (isExclusiveMinimum) { - expr = stdx::make_unique<GTMatchExpression>(); + expr = stdx::make_unique<GTMatchExpression>(path, minimum); } else { - expr = stdx::make_unique<GTEMatchExpression>(); - } - auto status = expr->init(path, minimum); - if (!status.isOK()) { - return status; + expr = stdx::make_unique<GTEMatchExpression>(path, minimum); } MatcherTypeSet restrictionType; @@ -316,11 +303,7 @@ StatusWithMatchExpression parseLength(StringData path, return {stdx::make_unique<AlwaysTrueMatchExpression>()}; } - auto expr = stdx::make_unique<T>(); - auto status = expr->init(path, parsedLength.getValue()); - if (!status.isOK()) { - return status; - } + auto expr = stdx::make_unique<T>(path, parsedLength.getValue()); return makeRestriction(restrictionType, path, std::move(expr), typeExpr); } @@ -337,14 +320,11 @@ StatusWithMatchExpression parsePattern(StringData path, return {stdx::make_unique<AlwaysTrueMatchExpression>()}; } - auto expr = stdx::make_unique<RegexMatchExpression>(); - // JSON Schema does not allow regex flags to be specified. constexpr auto emptyFlags = ""; - auto status = expr->init(path, pattern.valueStringData(), emptyFlags); - if (!status.isOK()) { - return status; - } + auto expr = + stdx::make_unique<RegexMatchExpression>(path, pattern.valueStringData(), emptyFlags); + return makeRestriction(BSONType::String, path, std::move(expr), typeExpr); } @@ -366,11 +346,8 @@ StatusWithMatchExpression parseMultipleOf(StringData path, return {stdx::make_unique<AlwaysTrueMatchExpression>()}; } - auto expr = stdx::make_unique<InternalSchemaFmodMatchExpression>(); - auto status = expr->init(path, multipleOf.numberDecimal(), Decimal128(0)); - if (!status.isOK()) { - return status; - } + auto expr = stdx::make_unique<InternalSchemaFmodMatchExpression>( + path, multipleOf.numberDecimal(), Decimal128(0)); MatcherTypeSet restrictionType; restrictionType.allNumbers = true; @@ -445,16 +422,12 @@ StatusWithMatchExpression parseEnum(StringData path, BSONElement enumElement) { // Top-level non-object enum values can be safely ignored, since MongoDB only stores // objects, not scalars or arrays. if (arrayElem.type() == BSONType::Object) { - auto rootDocEq = stdx::make_unique<InternalSchemaRootDocEqMatchExpression>(); - rootDocEq->init(arrayElem.embeddedObject()); + auto rootDocEq = stdx::make_unique<InternalSchemaRootDocEqMatchExpression>( + arrayElem.embeddedObject()); orExpr->add(rootDocEq.release()); } } else { - auto eqExpr = stdx::make_unique<InternalSchemaEqMatchExpression>(); - auto initStatus = eqExpr->init(path, arrayElem); - if (!initStatus.isOK()) { - return initStatus; - } + auto eqExpr = stdx::make_unique<InternalSchemaEqMatchExpression>(path, arrayElem); orExpr->add(eqExpr.release()); } @@ -520,17 +493,13 @@ StatusWithMatchExpression translateRequired( auto andExpr = stdx::make_unique<AndMatchExpression>(); for (auto&& propertyName : requiredProperties) { - auto existsExpr = stdx::make_unique<ExistsMatchExpression>(); - invariantOK(existsExpr->init(propertyName)); + auto existsExpr = stdx::make_unique<ExistsMatchExpression>(propertyName); if (path.empty()) { andExpr->add(existsExpr.release()); } else { - auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto objectMatchStatus = objectMatch->init(std::move(existsExpr), path); - if (!objectMatchStatus.isOK()) { - return objectMatchStatus; - } + auto objectMatch = + stdx::make_unique<InternalSchemaObjectMatchExpression>(path, std::move(existsExpr)); andExpr->add(objectMatch.release()); } @@ -580,11 +549,10 @@ StatusWithMatchExpression parseProperties( } else { // This property either must not exist or must match the nested schema. Therefore, we // generate the match expression (OR (NOT (EXISTS)) <nestedSchemaMatch>). - auto existsExpr = stdx::make_unique<ExistsMatchExpression>(); - invariantOK(existsExpr->init(property.fieldNameStringData())); + auto existsExpr = + stdx::make_unique<ExistsMatchExpression>(property.fieldNameStringData()); - auto notExpr = stdx::make_unique<NotMatchExpression>(); - invariantOK(notExpr->init(existsExpr.release())); + auto notExpr = stdx::make_unique<NotMatchExpression>(existsExpr.release()); auto orExpr = stdx::make_unique<OrMatchExpression>(); orExpr->add(notExpr.release()); @@ -600,11 +568,8 @@ StatusWithMatchExpression parseProperties( return {std::move(andExpr)}; } - auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto objectMatchStatus = objectMatch->init(std::move(andExpr), path); - if (!objectMatchStatus.isOK()) { - return objectMatchStatus; - } + auto objectMatch = + stdx::make_unique<InternalSchemaObjectMatchExpression>(path, std::move(andExpr)); return makeRestriction(BSONType::Object, path, std::move(objectMatch), typeExpr); } @@ -717,15 +682,11 @@ StatusWithMatchExpression parseAllowedProperties(StringData path, auto otherwiseWithPlaceholder = stdx::make_unique<ExpressionWithPlaceholder>( kNamePlaceholder.toString(), std::move(otherwiseExpr.getValue())); - auto allowedPropertiesExpr = - stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>(); - auto status = allowedPropertiesExpr->init(std::move(propertyNames), - kNamePlaceholder, - std::move(patternProperties.getValue()), - std::move(otherwiseWithPlaceholder)); - if (!status.isOK()) { - return status; - } + auto allowedPropertiesExpr = stdx::make_unique<InternalSchemaAllowedPropertiesMatchExpression>( + std::move(propertyNames), + kNamePlaceholder, + std::move(patternProperties.getValue()), + std::move(otherwiseWithPlaceholder)); // If this is a top-level schema, then we have no path and there is no need for an explicit // object match node. @@ -733,11 +694,8 @@ StatusWithMatchExpression parseAllowedProperties(StringData path, return {std::move(allowedPropertiesExpr)}; } - auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto objectMatchStatus = objectMatch->init(std::move(allowedPropertiesExpr), path); - if (!objectMatchStatus.isOK()) { - return objectMatchStatus; - } + auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>( + path, std::move(allowedPropertiesExpr)); return makeRestriction(BSONType::Object, path, std::move(objectMatch), typeExpr); } @@ -755,39 +713,28 @@ StatusWithMatchExpression parseNumProperties(StringData path, return parsedNumProps.getStatus(); } - auto expr = stdx::make_unique<T>(); - auto status = expr->init(parsedNumProps.getValue()); - if (!status.isOK()) { - return status; - } + auto expr = stdx::make_unique<T>(parsedNumProps.getValue()); if (path.empty()) { // This is a top-level schema. return {std::move(expr)}; } - auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto objectMatchStatus = objectMatch->init(std::move(expr), path); - if (!objectMatchStatus.isOK()) { - return objectMatchStatus; - } + auto objectMatch = + stdx::make_unique<InternalSchemaObjectMatchExpression>(path, std::move(expr)); return makeRestriction(BSONType::Object, path, std::move(objectMatch), typeExpr); } StatusWithMatchExpression makeDependencyExistsClause(StringData path, StringData dependencyName) { - auto existsExpr = stdx::make_unique<ExistsMatchExpression>(); - invariantOK(existsExpr->init(dependencyName)); + auto existsExpr = stdx::make_unique<ExistsMatchExpression>(dependencyName); if (path.empty()) { return {std::move(existsExpr)}; } - auto objectMatch = stdx::make_unique<InternalSchemaObjectMatchExpression>(); - auto status = objectMatch->init(std::move(existsExpr), path); - if (!status.isOK()) { - return status; - } + auto objectMatch = + stdx::make_unique<InternalSchemaObjectMatchExpression>(path, std::move(existsExpr)); return {std::move(objectMatch)}; } @@ -807,10 +754,12 @@ StatusWithMatchExpression translateSchemaDependency(StringData path, return ifClause.getStatus(); } - auto condExpr = stdx::make_unique<InternalSchemaCondMatchExpression>(); - condExpr->init({std::move(ifClause.getValue()), - std::move(nestedSchemaMatch.getValue()), - stdx::make_unique<AlwaysTrueMatchExpression>()}); + std::array<std::unique_ptr<MatchExpression>, 3> expressions = { + std::move(ifClause.getValue()), + std::move(nestedSchemaMatch.getValue()), + stdx::make_unique<AlwaysTrueMatchExpression>()}; + + auto condExpr = stdx::make_unique<InternalSchemaCondMatchExpression>(std::move(expressions)); return {std::move(condExpr)}; } @@ -861,10 +810,12 @@ StatusWithMatchExpression translatePropertyDependency(StringData path, BSONEleme return ifClause.getStatus(); } - auto condExpr = stdx::make_unique<InternalSchemaCondMatchExpression>(); - condExpr->init({std::move(ifClause.getValue()), - std::move(propertyDependencyExpr), - stdx::make_unique<AlwaysTrueMatchExpression>()}); + std::array<std::unique_ptr<MatchExpression>, 3> expressions = { + {std::move(ifClause.getValue()), + std::move(propertyDependencyExpr), + stdx::make_unique<AlwaysTrueMatchExpression>()}}; + + auto condExpr = stdx::make_unique<InternalSchemaCondMatchExpression>(std::move(expressions)); return {std::move(condExpr)}; } @@ -910,11 +861,7 @@ StatusWithMatchExpression parseUniqueItems(BSONElement uniqueItemsElt, } else if (path.empty()) { return {stdx::make_unique<AlwaysTrueMatchExpression>()}; } else if (uniqueItemsElt.boolean()) { - auto uniqueItemsExpr = stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(); - auto status = uniqueItemsExpr->init(path); - if (!status.isOK()) { - return status; - } + auto uniqueItemsExpr = stdx::make_unique<InternalSchemaUniqueItemsMatchExpression>(path); return makeRestriction(BSONType::Array, path, std::move(uniqueItemsExpr), typeExpr); } @@ -954,9 +901,8 @@ StatusWith<boost::optional<long long>> parseItems(StringData path, } auto exprWithPlaceholder = stdx::make_unique<ExpressionWithPlaceholder>( kNamePlaceholder.toString(), std::move(parsedSubschema.getValue())); - auto matchArrayIndex = - stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>(); - invariantOK(matchArrayIndex->init(path, index, std::move(exprWithPlaceholder))); + auto matchArrayIndex = stdx::make_unique<InternalSchemaMatchArrayIndexMatchExpression>( + path, index, std::move(exprWithPlaceholder)); andExprForSubschemas->add(matchArrayIndex.release()); ++index; } @@ -984,11 +930,10 @@ StatusWith<boost::optional<long long>> parseItems(StringData path, if (path.empty()) { andExpr->add(stdx::make_unique<AlwaysTrueMatchExpression>().release()); } else { - auto allElemMatch = - stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>(); constexpr auto startIndexForItems = 0LL; - invariantOK( - allElemMatch->init(path, startIndexForItems, std::move(exprWithPlaceholder))); + auto allElemMatch = + stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>( + path, startIndexForItems, std::move(exprWithPlaceholder)); andExpr->add(makeRestriction(BSONType::Array, path, std::move(allElemMatch), typeExpr) .release()); } @@ -1039,9 +984,8 @@ Status parseAdditionalItems(StringData path, andExpr->add(stdx::make_unique<AlwaysTrueMatchExpression>().release()); } else { auto allElemMatch = - stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>(); - invariantOK( - allElemMatch->init(path, *startIndexForAdditionalItems, std::move(otherwiseExpr))); + stdx::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>( + path, *startIndexForAdditionalItems, std::move(otherwiseExpr)); andExpr->add(makeRestriction(BSONType::Array, path, std::move(allElemMatch), typeExpr) .release()); } @@ -1129,11 +1073,7 @@ Status translateLogicalKeywords(StringMap<BSONElement>* keywordMap, return parsedExpr.getStatus(); } - auto notMatchExpr = stdx::make_unique<NotMatchExpression>(); - auto initStatus = notMatchExpr->init(parsedExpr.getValue().release()); - if (!initStatus.isOK()) { - return initStatus; - } + auto notMatchExpr = stdx::make_unique<NotMatchExpression>(parsedExpr.getValue().release()); andExpr->add(notMatchExpr.release()); } @@ -1556,11 +1496,14 @@ constexpr StringData JSONSchemaParser::kSchemaTypeString; StatusWithMatchExpression JSONSchemaParser::parse(BSONObj schema, bool ignoreUnknownKeywords) { LOG(5) << "Parsing JSON Schema: " << schema.jsonString(); - - auto translation = _parse(""_sd, schema, ignoreUnknownKeywords); - if (shouldLog(logger::LogSeverity::Debug(5)) && translation.isOK()) { - LOG(5) << "Translated schema match expression: " << translation.getValue()->toString(); + try { + auto translation = _parse(""_sd, schema, ignoreUnknownKeywords); + if (shouldLog(logger::LogSeverity::Debug(5)) && translation.isOK()) { + LOG(5) << "Translated schema match expression: " << translation.getValue()->toString(); + } + return translation; + } catch (const DBException& ex) { + return {ex.toStatus()}; } - return translation; } } // namespace mongo diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp index 358775136cd..9d3b6365266 100644 --- a/src/mongo/db/pipeline/document_source_match.cpp +++ b/src/mongo/db/pipeline/document_source_match.cpp @@ -447,10 +447,10 @@ boost::intrusive_ptr<DocumentSourceMatch> DocumentSourceMatch::descendMatchOnPat if (node->getCategory() == MatchExpression::MatchCategory::kLeaf && node->matchType() != MatchExpression::TYPE_OPERATOR) { auto leafNode = static_cast<LeafMatchExpression*>(node); - leafNode->setPath(newPath).transitional_ignore(); + leafNode->setPath(newPath); } else if (node->getCategory() == MatchExpression::MatchCategory::kArrayMatching) { auto arrayNode = static_cast<ArrayMatchingMatchExpression*>(node); - arrayNode->setPath(newPath).transitional_ignore(); + arrayNode->setPath(newPath); } }); diff --git a/src/mongo/db/query/planner_analysis_test.cpp b/src/mongo/db/query/planner_analysis_test.cpp index 783438a482c..23d794fd41c 100644 --- a/src/mongo/db/query/planner_analysis_test.cpp +++ b/src/mongo/db/query/planner_analysis_test.cpp @@ -177,10 +177,10 @@ TEST(QueryPlannerAnalysis, GeoSkipValidation) { QueryPlannerParams params; std::unique_ptr<FetchNode> fetchNodePtr = stdx::make_unique<FetchNode>(); - std::unique_ptr<GeoMatchExpression> exprPtr = stdx::make_unique<GeoMatchExpression>(); + std::unique_ptr<GeoMatchExpression> exprPtr = + stdx::make_unique<GeoMatchExpression>("geometry.field", nullptr, BSONObj()); GeoMatchExpression* expr = exprPtr.get(); - expr->init("geometry.field", nullptr, BSONObj()).transitional_ignore(); FetchNode* fetchNode = fetchNodePtr.get(); // Takes ownership. diff --git a/src/mongo/dbtests/extensions_callback_real_test.cpp b/src/mongo/dbtests/extensions_callback_real_test.cpp index 7ea4e6a4af0..2e342f06645 100644 --- a/src/mongo/dbtests/extensions_callback_real_test.cpp +++ b/src/mongo/dbtests/extensions_callback_real_test.cpp @@ -79,11 +79,10 @@ protected: TEST_F(ExtensionsCallbackRealTest, TextNoIndex) { BSONObj query = fromjson("{$text: {$search:\"awesome\"}}"); - StatusWithMatchExpression result = - ExtensionsCallbackReal(&_opCtx, &_nss).parseText(query.firstElement()); - - ASSERT_NOT_OK(result.getStatus()); - ASSERT_EQ(ErrorCodes::IndexNotFound, result.getStatus()); + ASSERT_THROWS_CODE(StatusWithMatchExpression result( + ExtensionsCallbackReal(&_opCtx, &_nss).parseText(query.firstElement())), + AssertionException, + ErrorCodes::IndexNotFound); } TEST_F(ExtensionsCallbackRealTest, TextBasic) { @@ -116,10 +115,10 @@ TEST_F(ExtensionsCallbackRealTest, TextLanguageError) { false)); // isUnique BSONObj query = fromjson("{$text: {$search:\"awesome\", $language:\"spanglish\"}}"); - StatusWithMatchExpression result = - ExtensionsCallbackReal(&_opCtx, &_nss).parseText(query.firstElement()); - - ASSERT_NOT_OK(result.getStatus()); + ASSERT_THROWS_CODE(StatusWithMatchExpression result( + ExtensionsCallbackReal(&_opCtx, &_nss).parseText(query.firstElement())), + AssertionException, + ErrorCodes::BadValue); } TEST_F(ExtensionsCallbackRealTest, TextCaseSensitiveTrue) { diff --git a/src/mongo/s/shard_key_pattern.cpp b/src/mongo/s/shard_key_pattern.cpp index 549e753ea65..409bc54ec83 100644 --- a/src/mongo/s/shard_key_pattern.cpp +++ b/src/mongo/s/shard_key_pattern.cpp @@ -209,7 +209,7 @@ BSONObj ShardKeyPattern::normalizeShardKey(const BSONObj& shardKey) const { static BSONElement extractKeyElementFromMatchable(const MatchableDocument& matchable, StringData pathStr) { ElementPath path; - path.init(pathStr).transitional_ignore(); + path.init(pathStr); path.setTraverseNonleafArrays(false); path.setTraverseLeafArray(false); |