diff options
author | Davis Haupt <davis.haupt@mongodb.com> | 2022-11-11 18:16:45 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-11-11 19:43:06 +0000 |
commit | 016c6eb217c686732fb288e16e6c344ef6fea1f7 (patch) | |
tree | ceb2cf2a8ee561b90117f617dff7e3a33fe54e16 | |
parent | 61dd3a14b837d1e9a9ac567a37245cbe7a9be6a5 (diff) | |
download | mongo-016c6eb217c686732fb288e16e6c344ef6fea1f7.tar.gz |
SERVER-71214 remove $between
29 files changed, 46 insertions, 635 deletions
diff --git a/jstests/core/between.js b/jstests/core/between.js deleted file mode 100644 index 7416eb67672..00000000000 --- a/jstests/core/between.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Tests the $between operator in simple form in the match language on unencrypted data. - * @tags: [ requires_fcv_62, multiversion_incompatible ] - */ - -(function() { -"use strict"; - -load('jstests/aggregation/extras/utils.js'); // For assertArrayEq. -load('jstests/libs/analyze_plan.js'); // For getWinningPlan. - -const coll = db.between_coll; -coll.drop(); - -// populate the collection with various values. -let i; -for (i = 0; i < 10; i++) { - assert.commandWorked(coll.insert({v: i, _id: i})); -} -assert.commandWorked(coll.insert({v: NumberLong(4), _id: i++})); -assert.commandWorked(coll.insert({v: NumberDecimal(9.2855), _id: i++})); - -let stringVals = ["hello", "world", "galaxy", "apple", "apartment"]; -stringVals.forEach(string => { - assert.commandWorked(coll.insert({v: string, _id: i++})); -}); - -assert.commandWorked(coll.insert({v: [2, 4, 6], _id: i++})); -assert.commandWorked(coll.insert({v: [2, "galaxy", [8]], _id: i++})); -assert.commandWorked(coll.insert({v: ISODate("1998-08-03T20:34:00.000Z"), _id: i++})); -assert.commandWorked(coll.insert({v: ISODate("2022-01-01T00:00:00.000Z"), _id: i++})); - -// $between given an array of numbers. -let expected = [{v: 3}, {v: 4}, {v: NumberLong(4)}, {v: 5}, {v: 6}, {v: 7}, {v: 8}, {v: [2, 4, 6]}]; -assertArrayEq( - {actual: coll.find({v: {$between: [3, 8]}}).toArray(), expected, fieldsToSkip: ["_id"]}); - -// $between given an array of dates. -expected = [{v: ISODate("1998-08-03T20:34:00.000Z")}]; -assertArrayEq({ - actual: - coll.find({ - v: { - $between: - [ISODate("1996-02-03T20:34:00.000Z"), ISODate("2000-04-03T20:34:00.000Z")] - } - }) - .toArray(), - expected, - fieldsToSkip: ["_id"] -}); - -// $between nested inide a $not expression. -expected = [ - {v: 0}, - {v: 1}, - {v: 2}, - {v: 9}, - {v: NumberDecimal(9.2855)}, - {v: "hello"}, - {v: "world"}, - {v: "galaxy"}, - {v: "apple"}, - {v: "apartment"}, - {v: [2, "galaxy", [8]]}, - {v: ISODate("1998-08-03T20:34:00.000Z")}, - {v: ISODate("2022-01-01T00:00:00.000Z")} -]; -assertArrayEq({ - actual: coll.find({v: {$not: {$between: [3, 8]}}}).toArray(), - expected, - fieldsToSkip: ["_id"] -}); - -// $between inline with other expressions. -expected = [{v: 0}, {v: "galaxy"}, {v: "apple"}, {v: "apartment"}, {v: [2, "galaxy", [8]]}]; -assertArrayEq({ - actual: coll.find({$or: [{v: 0}, {v: {$between: ['a', 'gb']}}]}).toArray(), - expected, - fieldsToSkip: ["_id"] -}); - -// $between returns empty result. -expected = []; -assertArrayEq({actual: coll.find({v: {$between: [NumberInt(32), {}]}}).toArray(), expected}); - -// $between uses an index scan with arrays. -coll.createIndex({v: 1}); -let betweenExplainArray = coll.find({v: {$between: [2, 5]}}).explain().queryPlanner; -let winningPlan = getWinningPlan(betweenExplainArray); -assert(isIxscan(db, winningPlan)); - -// $between uses an index scan with the proper bounds without arrays. -coll.dropIndex({v: 1}); -assert.commandWorked(coll.deleteOne({v: [2, "galaxy", [8]], _id: 18})); -assert.commandWorked(coll.deleteOne({v: [2, 4, 6], _id: 17})); -coll.createIndex({v: 1}); - -winningPlan = getWinningPlan(coll.find({v: {$between: [2, 5]}}).explain().queryPlanner); -let stages = getPlanStages(winningPlan, "IXSCAN"); -assert(isIxscan(db, winningPlan)); -stages.forEach(stage => { - assert.eq({v: ["[2.0, 5.0]"]}, stage.indexBounds); -}); - -// $between must fail if the array does not have 2 elements in it. -assert.throwsWithCode(() => { - coll.find({v: {$between: [1]}}).toArray(); -}, ErrorCodes.FailedToParse); - -// $between must fail if the array does not have 2 elements in it. -assert.throwsWithCode(() => { - coll.find({v: {$between: [1, 2, 4]}}).toArray(); -}, ErrorCodes.FailedToParse); - -// $between must fail if the input is not binData or an array. -assert.throwsWithCode(() => { - coll.find({v: {$between: "apartment"}}).toArray(); -}, ErrorCodes.BadValue); - -// $between must fail if the input is not binData or an array. -assert.throwsWithCode(() => { - coll.find({v: {$between: NumberDecimal(100.32)}}).toArray(); -}, ErrorCodes.BadValue); -})(); diff --git a/src/mongo/db/matcher/doc_validation_error.cpp b/src/mongo/db/matcher/doc_validation_error.cpp index d9240f09429..721f7b81c8e 100644 --- a/src/mongo/db/matcher/doc_validation_error.cpp +++ b/src/mongo/db/matcher/doc_validation_error.cpp @@ -1185,8 +1185,6 @@ public: MONGO_UNREACHABLE; } - void visit(const BetweenMatchExpression* expr) final {} - private: // Set of utilities responsible for appending various fields to build a descriptive error. void appendOperatorName(const MatchExpression& expr) { @@ -1918,7 +1916,6 @@ public: void visit(const WhereNoOpMatchExpression* expr) final { MONGO_UNREACHABLE; } - void visit(const BetweenMatchExpression* expr) final {} private: /** @@ -2232,9 +2229,6 @@ public: void visit(const WhereNoOpMatchExpression* expr) final { MONGO_UNREACHABLE; } - void visit(const BetweenMatchExpression* expr) final { - _context->finishCurrentError(expr); - } private: void postVisitTreeOperator(const ListOfMatchExpression* expr, diff --git a/src/mongo/db/matcher/expression.h b/src/mongo/db/matcher/expression.h index 96de6cc82c1..a56139a343c 100644 --- a/src/mongo/db/matcher/expression.h +++ b/src/mongo/db/matcher/expression.h @@ -86,7 +86,6 @@ public: BITS_ALL_CLEAR, BITS_ANY_SET, BITS_ANY_CLEAR, - BETWEEN, // Negations. NOT, diff --git a/src/mongo/db/matcher/expression_algo.cpp b/src/mongo/db/matcher/expression_algo.cpp index e69f2aa0122..eb82de9d874 100644 --- a/src/mongo/db/matcher/expression_algo.cpp +++ b/src/mongo/db/matcher/expression_algo.cpp @@ -578,7 +578,6 @@ std::unique_ptr<MatchExpression> splitMatchExpressionForColumns( case MatchExpression::ALWAYS_TRUE: case MatchExpression::ELEM_MATCH_OBJECT: case MatchExpression::ELEM_MATCH_VALUE: // This one should be feasible. May be valuable. - case MatchExpression::BETWEEN: case MatchExpression::EXPRESSION: case MatchExpression::GEO: case MatchExpression::GEO_NEAR: diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp index fdb7434b91a..9ee94f9a7c3 100644 --- a/src/mongo/db/matcher/expression_leaf.cpp +++ b/src/mongo/db/matcher/expression_leaf.cpp @@ -884,18 +884,4 @@ bool BitTestMatchExpression::equivalent(const MatchExpression* other) const { return path() == realOther->path() && myBitPositions == otherBitPositions; } - -void BetweenMatchExpression::debugString(StringBuilder& debug, int indentationLevel) const { - _debugAddSpace(debug, indentationLevel); - debug << path() << " " << kName; - debug << " " << rhs().toString(false); - - MatchExpression::TagData* td = getTag(); - if (td) { - debug << " "; - td->debugString(&debug); - } - - debug << "\n"; -} } // namespace mongo diff --git a/src/mongo/db/matcher/expression_leaf.h b/src/mongo/db/matcher/expression_leaf.h index 35721d3c2fe..64c20b4b2fe 100644 --- a/src/mongo/db/matcher/expression_leaf.h +++ b/src/mongo/db/matcher/expression_leaf.h @@ -1074,68 +1074,4 @@ public: visitor->visit(this); } }; - -/** - * MatchExpression that represents a filter for a range of values. Similar semantics to the BETWEEN - * SQL operator. - */ -class BetweenMatchExpression final : public LeafMatchExpression { -public: - static constexpr StringData kName = "$between"_sd; - - BetweenMatchExpression(boost::optional<StringData> path, - BSONElement rhs, - clonable_ptr<ErrorAnnotation> annotation = nullptr) - : LeafMatchExpression(BETWEEN, path, annotation) { - _backingBSON = BSON("" << rhs); - } - - - BSONElement rhs() const { - return _backingBSON.firstElement(); - } - - bool matchesSingleElement(const BSONElement& e, MatchDetails* details = nullptr) const final { - tasserted(6762800, "$between should be rewritten before execution."); - } - - BSONObj getSerializedRightHandSide() const final { - return BSON(kName << _backingBSON.firstElement()); - } - - std::unique_ptr<MatchExpression> shallowClone() const final { - std::unique_ptr<BetweenMatchExpression> e = - std::make_unique<BetweenMatchExpression>(path(), rhs(), _errorAnnotation); - if (getTag()) { - e->setTag(getTag()->clone()); - } - return e; - } - - virtual bool equivalent(const MatchExpression* other) const { - if (matchType() != other->matchType()) { - return false; - } - auto otherCast = static_cast<const BetweenMatchExpression*>(other); - return path() == otherCast->path() && rhs().binaryEqual(otherCast->rhs()); - }; - - void debugString(StringBuilder& debug, int indentationLevel) const; - - void acceptVisitor(MatchExpressionMutableVisitor* visitor) final { - visitor->visit(this); - } - - void acceptVisitor(MatchExpressionConstVisitor* visitor) const final { - visitor->visit(this); - } - -private: - BSONObj _backingBSON; - - ExpressionOptimizerFunc getOptimizer() const final { - return [](std::unique_ptr<MatchExpression> expression) { return expression; }; - } -}; - } // namespace mongo diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp index 8b01b606683..e99605bdc22 100644 --- a/src/mongo/db/matcher/expression_leaf_test.cpp +++ b/src/mongo/db/matcher/expression_leaf_test.cpp @@ -2268,61 +2268,4 @@ DEATH_TEST_REGEX(ComparisonMatchExpression, ASSERT_EQ(eq.numChildren(), 0); ASSERT_THROWS_CODE(eq.getChild(0), AssertionException, 6400209); } - -TEST(BetweenMatchExpression, EqualWithoutCollator) { - BSONObj operand = BSON("a" << 5); - BetweenMatchExpression eb1("a"_sd, operand["a"]); - BetweenMatchExpression eb2("a"_sd, operand["a"]); - ASSERT(eb1.equivalent(&eb2)); -} - - -TEST(BetweenMatchExpression, UnequalWithoutCollator) { - BSONObj operand = BSON("a" << 5 << "b" << 10); - BetweenMatchExpression eb1("a"_sd, operand["a"]); - BetweenMatchExpression eb2("a"_sd, operand["b"]); - ASSERT_FALSE(eb1.equivalent(&eb2)); -} - - -TEST(BetweenMatchExpression, UnequalDueToPath) { - BSONObj operand = BSON("a" << 5 << "b" << 10); - BetweenMatchExpression eb1("a"_sd, operand["a"]); - BetweenMatchExpression eb2("b"_sd, operand["a"]); - ASSERT_FALSE(eb1.equivalent(&eb2)); -} - -TEST(BetweenMatchExpression, UnequalDueToRhs) { - BSONObj operand = BSON("a" << 5 << "b" << 10); - BetweenMatchExpression eb1("a"_sd, operand["a"]); - BetweenMatchExpression eb2("a"_sd, operand["b"]); - ASSERT_FALSE(eb1.equivalent(&eb2)); -} - -TEST(BetweenMatchExpression, CanSerializeToBSON) { - auto op = BSON("$between" << BSON_ARRAY(1 << 5)); - BetweenMatchExpression eb("a"_sd, op.firstElement()); - BSONObjBuilder bob; - eb.serialize(&bob, true); - ASSERT_BSONOBJ_EQ(bob.obj(), BSON("a" << op)); -} - -TEST(BetweenMatchExpression, CanSerializeToBSONInsideAnd) { - auto op = BSON("$between" << BSON_ARRAY(1 << 5)); - auto eb = std::make_unique<BetweenMatchExpression>("a"_sd, op.firstElement()); - auto v = std::vector<std::unique_ptr<MatchExpression>>(); - v.push_back(std::move(eb)); - AndMatchExpression nd(std::move(v)); - BSONObjBuilder bob; - nd.serialize(&bob, true); - ASSERT_BSONOBJ_EQ(bob.obj(), BSON("$and" << BSON_ARRAY(BSON("a" << op)))); -} - -DEATH_TEST_REGEX(BetweenMatchExpression, ErrorsOnEvaluation, "*.6762800") { - auto op = BSON("$between" << BSON_ARRAY(1 << 5)); - auto obj = BSON("$between" << 2); - BetweenMatchExpression eb(""_sd, op.firstElement()); - ASSERT_THROWS_CODE(eb.matchesSingleElement(obj.firstElement()), DBException, 6762800); -} - } // namespace mongo diff --git a/src/mongo/db/matcher/expression_parameterization.h b/src/mongo/db/matcher/expression_parameterization.h index d9d384ea9df..57816d5de30 100644 --- a/src/mongo/db/matcher/expression_parameterization.h +++ b/src/mongo/db/matcher/expression_parameterization.h @@ -90,7 +90,6 @@ public: void visit(BitsAllSetMatchExpression* expr) final; void visit(BitsAnyClearMatchExpression* expr) final; void visit(BitsAnySetMatchExpression* expr) final; - void visit(BetweenMatchExpression* expr) final {} void visit(ElemMatchObjectMatchExpression* matchExpr) final {} void visit(ElemMatchValueMatchExpression* matchExpr) final {} void visit(EqualityMatchExpression* expr) final; diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp index b514b648477..d902fd617a4 100644 --- a/src/mongo/db/matcher/expression_parser.cpp +++ b/src/mongo/db/matcher/expression_parser.cpp @@ -1804,36 +1804,6 @@ StatusWithMatchExpression parseSubField(const BSONObj& context, case PathAcceptingKeyword::GEO_NEAR: return {Status(ErrorCodes::BadValue, str::stream() << "near must be first in: " << context)}; - - case PathAcceptingKeyword::BETWEEN: { - if (e.type() == BSONType::BinData) { - uassert(ErrorCodes::BadValue, - "$between needs an encrypted binData", - e.binDataType() == BinDataType::Encrypt); - return std::make_unique<BetweenMatchExpression>( - name, - e, - doc_validation_error::createAnnotation(expCtx, - e.fieldNameStringData().toString(), - BSON((name ? *name : "") << e.wrap()))); - } else if (e.type() == BSONType::Array) { - auto betweenArray = e.embeddedObject(); - auto iter = BSONObjIterator(betweenArray); - if (!iter.more()) { - return Status(ErrorCodes::FailedToParse, "$between needs an array of size 2"); - } - auto first = iter.next(); - if (!iter.more()) { - return Status(ErrorCodes::FailedToParse, "$between needs an array of size 2"); - } - auto second = iter.next(); - if (iter.more()) { - return Status(ErrorCodes::FailedToParse, "$between needs an array of size 2"); - } - return parseBetweenWithArray(name, e, expCtx, allowedFeatures, first, second); - } - return {Status(ErrorCodes::BadValue, "$between needs an array or binData ")}; - } case PathAcceptingKeyword::INTERNAL_EXPR_EQ: { if (e.type() == BSONType::Undefined || e.type() == BSONType::Array) { return {Status(ErrorCodes::BadValue, @@ -2230,7 +2200,6 @@ MONGO_INITIALIZER(MatchExpressionParser)(InitializerContext* context) { {"bitsAnyClear", PathAcceptingKeyword::BITS_ANY_CLEAR}, {"bitsAnySet", PathAcceptingKeyword::BITS_ANY_SET}, {"elemMatch", PathAcceptingKeyword::ELEM_MATCH}, - {"between", PathAcceptingKeyword::BETWEEN}, {"eq", PathAcceptingKeyword::EQUALITY}, {"exists", PathAcceptingKeyword::EXISTS}, {"geoIntersects", PathAcceptingKeyword::GEO_INTERSECTS}, diff --git a/src/mongo/db/matcher/expression_parser.h b/src/mongo/db/matcher/expression_parser.h index 3bc7e3be141..101a7e10332 100644 --- a/src/mongo/db/matcher/expression_parser.h +++ b/src/mongo/db/matcher/expression_parser.h @@ -55,7 +55,6 @@ enum class PathAcceptingKeyword { BITS_ANY_CLEAR, BITS_ANY_SET, ELEM_MATCH, - BETWEEN, EQUALITY, EXISTS, GEO_INTERSECTS, diff --git a/src/mongo/db/matcher/expression_parser_test.cpp b/src/mongo/db/matcher/expression_parser_test.cpp index ba8b41b5e05..4e2a02ab6d9 100644 --- a/src/mongo/db/matcher/expression_parser_test.cpp +++ b/src/mongo/db/matcher/expression_parser_test.cpp @@ -811,106 +811,4 @@ TEST(InternalSchemaBinDataEncryptedTypeExpressionTest, NonBinDataValueDoesNotMat BSONObj notMatch = BSON("a" << BSONArray()); ASSERT_FALSE(expr->matchesBSON(notMatch)); } - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorRHSNumeric) { - BSONObj query = fromjson("{'a': {$between: [3.10, 6.20]}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - - ASSERT_TRUE(result.isOK()); - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::AND); - result.getValue()->matchesBSON(fromjson("{a: {$gte: 3.10, $lte: 6.20}}")); -} - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorRHSDate) { - Date_t date = Date_t::now(); - Date_t pastDate = date - Seconds(100); - BSONObj query = BSON("a" << BSON("$between" << BSON_ARRAY(pastDate << date))); - BSONObj greater = BSON("$gte" << pastDate); - BSONObj lesser = BSON("$lte" << date); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - - ASSERT_TRUE(result.isOK()); - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::AND); - result.getValue()->matchesBSON(BSON("a" << BSON_ARRAY(greater << lesser))); -} - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorInsideAnd) { - BSONObj query = - fromjson("{$and: [{ a: { $ne: 'yellow' }}, {a: {$between: ['galaxy', 'zebra']}}]}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - ASSERT_TRUE(result.isOK()); - - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::AND); - ASSERT_EQ(result.getValue()->getChild(0)->matchType(), MatchExpression::NOT); - - auto ptr = result.getValue()->getChild(1); - ASSERT_EQ(ptr->matchType(), MatchExpression::AND); - ptr->matchesBSON(fromjson("{a: {$gte: 'galaxy', $lte: 'zebra'}}")); -} - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorInsideNot) { - BSONObj query = fromjson("{a: {$not: {$between: [3, 5]}}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - ASSERT_TRUE(result.isOK()); - - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::NOT); - ASSERT_EQ(result.getValue()->getChild(0)->matchType(), MatchExpression::AND); - - auto ptr = result.getValue()->getChild(0)->getChild(0); - ptr->matchesBSON(fromjson("{a: {$gte: 3, $lte: 5}}")); -} - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorDottedPath) { - BSONObj query = fromjson("{'a.b': {$between: [3, 5]}}"); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - - ASSERT_TRUE(result.isOK()); - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::AND); - result.getValue()->matchesBSON(fromjson("{'a.b': {$gte: 3, $lte: 5}}")); -} - -TEST(BetweenMatchExpressionTest, BetweenExpectedBehaviorBinData) { - uint8_t bytes[] = {0, 1, 2, 3, 4, 5}; - BSONObj match = BSON("a" << BSON("$between" << BSONBinData(bytes, 5, BinDataType::Encrypt))); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(match, expCtx); - ASSERT_TRUE(result.isOK()); - ASSERT_EQ(result.getValue()->matchType(), MatchExpression::BETWEEN); -} - -TEST(BetweenMatchExpressionTest, BetweenFailsWithUnencryptedBinData) { - uint8_t bytes[] = {0, 1, 2, 3, 4, 5}; - BSONObj match = BSON("a" << BSON("$between" << BSONBinData(bytes, 5, BinDataType::bdtCustom))); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(match, expCtx); - ASSERT_EQ(result.getStatus(), ErrorCodes::BadValue); -} - -TEST(BetweenMatchExpressionTest, BetweenFailsToParseArrayTooSmall) { - BSONObj query = BSON("a" << BSON("$between" << BSON_ARRAY(1))); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse); -} - -TEST(BetweenMatchExpressionTest, BetweenFailsToParseArrayTooLarge) { - BSONObj query = BSON("a" << BSON("$between" << BSON_ARRAY(1 << 5 << "apple"))); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - ASSERT_EQ(result.getStatus(), ErrorCodes::FailedToParse); -} - -TEST(BetweenMatchExpressionTest, BetweenFailsWithBadValue) { - BSONObj query = BSON("a" << BSON("$between" - << "galaxy")); - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx); - ASSERT_EQ(result.getStatus(), ErrorCodes::BadValue); -} - } // namespace mongo diff --git a/src/mongo/db/matcher/expression_visitor.h b/src/mongo/db/matcher/expression_visitor.h index 2aa4c3aefe0..76d1288eb82 100644 --- a/src/mongo/db/matcher/expression_visitor.h +++ b/src/mongo/db/matcher/expression_visitor.h @@ -55,7 +55,6 @@ class InternalExprGTMatchExpression; class InternalExprGTEMatchExpression; class InternalExprLTMatchExpression; class InternalExprLTEMatchExpression; -class BetweenMatchExpression; class InternalSchemaAllElemMatchFromIndexMatchExpression; class InternalSchemaAllowedPropertiesMatchExpression; class InternalSchemaBinDataEncryptedTypeExpression; @@ -163,7 +162,6 @@ public: virtual void visit(MaybeConstPtr<TypeMatchExpression> expr) = 0; virtual void visit(MaybeConstPtr<WhereMatchExpression> expr) = 0; virtual void visit(MaybeConstPtr<WhereNoOpMatchExpression> expr) = 0; - virtual void visit(MaybeConstPtr<BetweenMatchExpression> expr) = 0; }; using MatchExpressionMutableVisitor = MatchExpressionVisitor<false>; @@ -249,7 +247,6 @@ struct SelectiveMatchExpressionVisitorBase : public MatchExpressionVisitor<IsCon void visit(MaybeConstPtr<TypeMatchExpression> expr) override {} void visit(MaybeConstPtr<WhereMatchExpression> expr) override {} void visit(MaybeConstPtr<WhereNoOpMatchExpression> expr) override {} - void visit(MaybeConstPtr<BetweenMatchExpression> expr) override {} }; } // namespace mongo diff --git a/src/mongo/db/matcher/match_expression_dependencies.cpp b/src/mongo/db/matcher/match_expression_dependencies.cpp index c75fc6f21ba..6ff4a702def 100644 --- a/src/mongo/db/matcher/match_expression_dependencies.cpp +++ b/src/mongo/db/matcher/match_expression_dependencies.cpp @@ -327,10 +327,6 @@ public: void visit(const WhereNoOpMatchExpression* expr) override {} - void visit(const BetweenMatchExpression* expr) override { - visitPathExpression(expr); - } - private: void visitPathExpression(const PathMatchExpression* expr) { if (_ignoreDependencies) { diff --git a/src/mongo/db/pipeline/abt/agg_expression_visitor.cpp b/src/mongo/db/pipeline/abt/agg_expression_visitor.cpp index 737671c4c7f..c09c0d6b0ef 100644 --- a/src/mongo/db/pipeline/abt/agg_expression_visitor.cpp +++ b/src/mongo/db/pipeline/abt/agg_expression_visitor.cpp @@ -223,10 +223,6 @@ public: pushArithmeticBinaryExpr(expr, Operations::Div); } - void visit(const ExpressionBetween* expr) override final { - unsupportedExpression(expr->getOpName()); - } - void visit(const ExpressionExp* expr) override final { pushSingleArgFunctionFromTop("exp"); } diff --git a/src/mongo/db/pipeline/abt/match_expression_visitor.cpp b/src/mongo/db/pipeline/abt/match_expression_visitor.cpp index 458c9d88b00..ab728096d25 100644 --- a/src/mongo/db/pipeline/abt/match_expression_visitor.cpp +++ b/src/mongo/db/pipeline/abt/match_expression_visitor.cpp @@ -475,10 +475,6 @@ public: unsupportedExpression(expr); } - void visit(const BetweenMatchExpression* expr) override { - unsupportedExpression(expr); - } - private: void generateBoolConstant(const bool value) { _ctx.push<PathConstant>(Constant::boolean(value)); diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp index e116955b867..deb0e021399 100644 --- a/src/mongo/db/pipeline/document_source_match.cpp +++ b/src/mongo/db/pipeline/document_source_match.cpp @@ -267,7 +267,6 @@ Document redactSafePortionDollarOps(BSONObj expr) { } // These are never allowed - case PathAcceptingKeyword::BETWEEN: case PathAcceptingKeyword::EXISTS: case PathAcceptingKeyword::GEO_INTERSECTS: case PathAcceptingKeyword::GEO_NEAR: diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index 080faffe5c3..8d25a5b819c 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -7999,13 +7999,6 @@ Value ExpressionTsIncrement::evaluate(const Document& root, Variables* variables REGISTER_STABLE_EXPRESSION(tsIncrement, ExpressionTsIncrement::parse); -/* ------------------------- ExpressionBetween ----------------------------- */ - -Value ExpressionBetween::evaluate(const Document& root, Variables* variables) const { - tasserted(6882800, "$between does not have a runtime implementation."); -} - -REGISTER_STABLE_EXPRESSION(between, ExpressionBetween::parse); MONGO_INITIALIZER_GROUP(BeginExpressionRegistration, ("default"), ("EndExpressionRegistration")) MONGO_INITIALIZER_GROUP(EndExpressionRegistration, ("BeginExpressionRegistration"), ()) diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index 1046ada180d..eb28918bc05 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -4301,28 +4301,4 @@ public: } }; -class ExpressionBetween : public ExpressionFixedArity<ExpressionBetween, 2> { -public: - static constexpr const char* const opName = "$between"; - explicit ExpressionBetween(ExpressionContext* const expCtx) - : ExpressionFixedArity<ExpressionBetween, 2>(expCtx) {} - - ExpressionBetween(ExpressionContext* const expCtx, ExpressionVector&& children) - : ExpressionFixedArity<ExpressionBetween, 2>(expCtx, std::move(children)) {} - - Value evaluate(const Document& root, Variables* variables) const final; - - const char* getOpName() const final { - return opName; - } - - void acceptVisitor(ExpressionMutableVisitor* visitor) final { - return visitor->visit(this); - } - - void acceptVisitor(ExpressionConstVisitor* visitor) const final { - return visitor->visit(this); - } -}; - } // namespace mongo diff --git a/src/mongo/db/pipeline/expression_dependencies.cpp b/src/mongo/db/pipeline/expression_dependencies.cpp index f6a66fbe59d..cd2927025a3 100644 --- a/src/mongo/db/pipeline/expression_dependencies.cpp +++ b/src/mongo/db/pipeline/expression_dependencies.cpp @@ -181,7 +181,6 @@ public: void visit(const ExpressionObject*) {} void visit(const ExpressionInternalFLEEqual*) {} void visit(const ExpressionInternalFLEBetween*) {} - void visit(const ExpressionBetween*) {} }; class DependencyVisitor : public DefaultDependencyVisitor { diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index b2146b0a6b1..0a127596ae2 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -4219,35 +4219,6 @@ TEST(ExpressionFLETest, TestBinData_RoundTrip) { ASSERT_BSONOBJ_EQ(value.getDocument().toBson(), roundTripExpr); } -TEST(ExpressionBetweenTest, ParseRoundTrip) { - auto input = fromjson(R"({$between: [ - "age", - {$binary: { - "base64": "ZW5jcnlwdGVkIHBheWxvYWQ=", - "subType": "6" - }}]})"); - auto expCtx = ExpressionContextForTest(); - auto vps = expCtx.variablesParseState; - auto expr = ExpressionBetween::parse(&expCtx, input.firstElement(), vps); - auto serializedExpr = expr->serialize(false); - auto expectedExpr = fromjson(R"({$between: [ - {$const: "age"}, - { $const: - {$binary: { - "base64": "ZW5jcnlwdGVkIHBheWxvYWQ=", - "subType": "6" - }} - } - ]})"); - ASSERT_BSONOBJ_EQ(expectedExpr, serializedExpr.getDocument().toBson()); -} - -DEATH_TEST_REGEX(ExpressionBetweenTest, EvaluateFails, "*.6882800") { - ASSERT_THROWS_CODE( - evaluateExpression("$between", {"fieldpath"_sd, 1}), AssertionException, 6882800); -} - - TEST(ExpressionFLETest, ParseAndSerializeBetween) { auto expCtx = ExpressionContextForTest(); auto vps = expCtx.variablesParseState; diff --git a/src/mongo/db/pipeline/expression_visitor.h b/src/mongo/db/pipeline/expression_visitor.h index ca2b6478fa6..1c97b82ece5 100644 --- a/src/mongo/db/pipeline/expression_visitor.h +++ b/src/mongo/db/pipeline/expression_visitor.h @@ -66,7 +66,6 @@ class ExpressionDayOfMonth; class ExpressionDayOfWeek; class ExpressionDayOfYear; class ExpressionDivide; -class ExpressionBetween; class ExpressionExp; class ExpressionFieldPath; class ExpressionFilter; @@ -234,7 +233,6 @@ public: virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionDateToString>) = 0; virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionDateTrunc>) = 0; virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionDivide>) = 0; - virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionBetween>) = 0; virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionExp>) = 0; virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionFieldPath>) = 0; virtual void visit(expression_walker::MaybeConstPtr<IsConst, ExpressionFilter>) = 0; @@ -416,7 +414,6 @@ struct SelectiveConstExpressionVisitorBase : public ExpressionConstVisitor { void visit(const ExpressionDateToString*) override {} void visit(const ExpressionDateTrunc*) override {} void visit(const ExpressionDivide*) override {} - void visit(const ExpressionBetween*) override {} void visit(const ExpressionExp*) override {} void visit(const ExpressionFieldPath*) override {} void visit(const ExpressionFilter*) override {} diff --git a/src/mongo/db/query/bind_input_params.cpp b/src/mongo/db/query/bind_input_params.cpp index 667f5eff007..e62d2489800 100644 --- a/src/mongo/db/query/bind_input_params.cpp +++ b/src/mongo/db/query/bind_input_params.cpp @@ -244,7 +244,6 @@ public: void visit(const TextNoOpMatchExpression* expr) final {} void visit(const TwoDPtInAnnulusExpression* expr) final {} void visit(const WhereNoOpMatchExpression* expr) final {} - void visit(const BetweenMatchExpression* expr) final {} private: void visitComparisonMatchExpression(const ComparisonMatchExpressionBase* expr) { diff --git a/src/mongo/db/query/canonical_query_encoder.cpp b/src/mongo/db/query/canonical_query_encoder.cpp index 52344ab35f8..e0b74b5aeea 100644 --- a/src/mongo/db/query/canonical_query_encoder.cpp +++ b/src/mongo/db/query/canonical_query_encoder.cpp @@ -932,9 +932,6 @@ public: void visit(const TwoDPtInAnnulusExpression* expr) final { MONGO_UNREACHABLE_TASSERT(6142133); } - void visit(const BetweenMatchExpression* expr) final { - MONGO_UNREACHABLE_TASSERT(6762801); - } private: /** diff --git a/src/mongo/db/query/cqf_command_utils.cpp b/src/mongo/db/query/cqf_command_utils.cpp index 7ce8042ad97..5f0363675d9 100644 --- a/src/mongo/db/query/cqf_command_utils.cpp +++ b/src/mongo/db/query/cqf_command_utils.cpp @@ -345,10 +345,6 @@ public: unsupportedExpression(expr); } - void visit(const BetweenMatchExpression* expr) override { - unsupportedExpression(expr); - } - private: void unsupportedExpression(const MatchExpression* expr) { _eligible = false; diff --git a/src/mongo/db/query/fle/range_predicate.cpp b/src/mongo/db/query/fle/range_predicate.cpp index dcd71777782..852d03095de 100644 --- a/src/mongo/db/query/fle/range_predicate.cpp +++ b/src/mongo/db/query/fle/range_predicate.cpp @@ -42,19 +42,11 @@ namespace mongo::fle { -REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(BETWEEN, - RangePredicate, - gFeatureFlagFLE2Range); - REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(GT, RangePredicate, gFeatureFlagFLE2Range); REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(GTE, RangePredicate, gFeatureFlagFLE2Range); REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(LT, RangePredicate, gFeatureFlagFLE2Range); REGISTER_ENCRYPTED_MATCH_PREDICATE_REWRITE_WITH_FLAG(LTE, RangePredicate, gFeatureFlagFLE2Range); -REGISTER_ENCRYPTED_AGG_PREDICATE_REWRITE_WITH_FLAG(ExpressionBetween, - RangePredicate, - gFeatureFlagFLE2Range); - REGISTER_ENCRYPTED_AGG_PREDICATE_REWRITE_WITH_FLAG(ExpressionCompare, RangePredicate, gFeatureFlagFLE2Range); @@ -65,32 +57,27 @@ namespace { // predicate, then return null to the caller so that the rewrite can return null. std::pair<boost::intrusive_ptr<Expression>, Value> validateRangeOp(Expression* expr) { auto children = [&]() { - if (auto betweenExpr = dynamic_cast<ExpressionBetween*>(expr)) { - return betweenExpr->getChildren(); - } else { - auto cmpExpr = dynamic_cast<ExpressionCompare*>(expr); - tassert(6720901, - "Range rewrite should only be called with $between or comparison operator.", - cmpExpr); - switch (cmpExpr->getOp()) { - case ExpressionCompare::GT: - case ExpressionCompare::GTE: - case ExpressionCompare::LT: - case ExpressionCompare::LTE: - return cmpExpr->getChildren(); - - case ExpressionCompare::EQ: - case ExpressionCompare::NE: - case ExpressionCompare::CMP: - return std::vector<boost::intrusive_ptr<Expression>>(); - } + auto cmpExpr = dynamic_cast<ExpressionCompare*>(expr); + tassert( + 6720901, "Range rewrite should only be called with a comparison operator.", cmpExpr); + switch (cmpExpr->getOp()) { + case ExpressionCompare::GT: + case ExpressionCompare::GTE: + case ExpressionCompare::LT: + case ExpressionCompare::LTE: + return cmpExpr->getChildren(); + + case ExpressionCompare::EQ: + case ExpressionCompare::NE: + case ExpressionCompare::CMP: + return std::vector<boost::intrusive_ptr<Expression>>(); } return std::vector<boost::intrusive_ptr<Expression>>(); }(); if (children.empty()) { return {nullptr, Value()}; } - // Both ExpressionBetween and ExpressionCompare have a fixed arity of 2. + // ExpressionCompare has a fixed arity of 2. auto fieldpath = dynamic_cast<ExpressionFieldPath*>(children[0].get()); uassert(6720903, "first argument should be a fieldpath", fieldpath); auto secondArg = dynamic_cast<ExpressionConstant*>(children[1].get()); @@ -157,17 +144,7 @@ std::unique_ptr<MatchExpression> RangePredicate::rewriteToTagDisjunction( } return makeTagDisjunction(toBSONArray(generateTags(payload))); } - - tassert(6720900, - "Range rewrite should only be called with $between operator.", - expr->matchType() == MatchExpression::BETWEEN); - auto betExpr = static_cast<BetweenMatchExpression*>(expr); - auto payload = betExpr->rhs(); - - if (!isPayload(payload)) { - return nullptr; - } - return makeTagDisjunction(toBSONArray(generateTags(payload))); + MONGO_UNREACHABLE_TASSERT(6720900); } std::unique_ptr<Expression> RangePredicate::rewriteToTagDisjunction(Expression* expr) const { @@ -189,20 +166,24 @@ std::unique_ptr<Expression> RangePredicate::rewriteToTagDisjunction(Expression* std::unique_ptr<MatchExpression> RangePredicate::rewriteToRuntimeComparison( MatchExpression* expr) const { - BSONElement ffp; - if (auto compExpr = dynamic_cast<ComparisonMatchExpression*>(expr)) { - auto payload = compExpr->getData(); - if (!isPayload(payload)) { + auto compExpr = dynamic_cast<ComparisonMatchExpression*>(expr); + tassert(7121400, "Reange rewrite can only operate on comparison match expression", compExpr); + switch (compExpr->matchType()) { + case MatchExpression::GT: + case MatchExpression::LT: + case MatchExpression::GTE: + case MatchExpression::LTE: + break; + default: return nullptr; - } - // If this is a stub expression, replace expression with $alwaysTrue. - if (isStub(payload)) { - return std::make_unique<AlwaysTrueMatchExpression>(); - } - ffp = payload; - } else { - auto between = static_cast<BetweenMatchExpression*>(expr); - ffp = between->rhs(); + } + auto ffp = compExpr->getData(); + if (!isPayload(ffp)) { + return nullptr; + } + // If this is a stub expression, replace expression with $alwaysTrue. + if (isStub(ffp)) { + return std::make_unique<AlwaysTrueMatchExpression>(); } if (!isPayload(ffp)) { diff --git a/src/mongo/db/query/fle/range_predicate.h b/src/mongo/db/query/fle/range_predicate.h index 5fbd7484ad0..98d67a6e2b4 100644 --- a/src/mongo/db/query/fle/range_predicate.h +++ b/src/mongo/db/query/fle/range_predicate.h @@ -34,7 +34,7 @@ namespace mongo::fle { /** - * Rewrite for the encrypted range index, which expects a $between expression. + * Rewrite for the encrypted range index, which expects a comparison operator expression. */ class RangePredicate : public EncryptedPredicate { public: diff --git a/src/mongo/db/query/fle/range_predicate_test.cpp b/src/mongo/db/query/fle/range_predicate_test.cpp index 61110c19041..1c0796e5e95 100644 --- a/src/mongo/db/query/fle/range_predicate_test.cpp +++ b/src/mongo/db/query/fle/range_predicate_test.cpp @@ -117,10 +117,8 @@ TEST_F(RangePredicateRewriteTest, MatchRangeRewrite_NoStub) { auto expCtx = make_intrusive<ExpressionContextForTest>(); - std::vector<StringData> operators = {"$between", "$gt", "$gte", "$lte", "$lt"}; auto payload = fromjson("{x: [1, 2, 3, 4, 5, 6, 7, 8, 9]}"); - assertRewriteForOp<BetweenMatchExpression>(_predicate, payload.firstElement(), allTags); assertRewriteForOp<GTMatchExpression>(_predicate, payload.firstElement(), allTags); assertRewriteForOp<GTEMatchExpression>(_predicate, payload.firstElement(), allTags); assertRewriteForOp<LTMatchExpression>(_predicate, payload.firstElement(), allTags); @@ -132,7 +130,6 @@ TEST_F(RangePredicateRewriteTest, MatchRangeRewrite_Stub) { auto expCtx = make_intrusive<ExpressionContextForTest>(); - std::vector<StringData> operators = {"$between", "$gt", "$gte", "$lte", "$lt"}; auto payload = fromjson("{x: [1, 2, 3, 4, 5, 6, 7, 8, 9]}"); #define ASSERT_REWRITE_TO_TRUE(T) \ @@ -164,20 +161,6 @@ TEST_F(RangePredicateRewriteTest, MatchRangeRewrite_Stub) { TEST_F(RangePredicateRewriteTest, AggRangeRewrite_Stub) { RAIIServerParameterControllerForTest controller("featureFlagFLE2Range", true); - { - auto input = fromjson(str::stream() << "{$between: [\"$age\", {$literal: [1, 2, 3]}]}"); - auto inputExpr = - ExpressionBetween::parseExpression(&_expCtx, input, _expCtx.variablesParseState); - - auto expected = ExpressionConstant::create(&_expCtx, Value(true)); - - _predicate.isStubPayload = true; - auto actual = _predicate.rewrite(inputExpr.get()); - ASSERT(actual); - ASSERT_BSONOBJ_EQ(actual->serialize(false).getDocument().toBson(), - expected->serialize(false).getDocument().toBson()); - } - auto ops = {"$gt", "$lt", "$gte", "$lte"}; for (auto& op : ops) { auto input = fromjson(str::stream() << "{" << op << ": [\"$age\", {$literal: [1, 2, 3]}]}"); @@ -195,8 +178,8 @@ TEST_F(RangePredicateRewriteTest, AggRangeRewrite_Stub) { } TEST_F(RangePredicateRewriteTest, AggRangeRewrite) { - { - auto op = "$between"; + auto ops = {"$gt", "$lt", "$gte", "$lte"}; + for (auto& op : ops) { auto input = fromjson(str::stream() << "{" << op << ": [\"$age\", {$literal: [1, 2, 3]}]}"); auto inputExpr = ExpressionCompare::parseExpression(&_expCtx, input, _expCtx.variablesParseState); @@ -208,29 +191,14 @@ TEST_F(RangePredicateRewriteTest, AggRangeRewrite) { ASSERT_BSONOBJ_EQ(actual->serialize(false).getDocument().toBson(), expected->serialize(false).getDocument().toBson()); } - { - auto ops = {"$gt", "$lt", "$gte", "$lte"}; - for (auto& op : ops) { - auto input = - fromjson(str::stream() << "{" << op << ": [\"$age\", {$literal: [1, 2, 3]}]}"); - auto inputExpr = - ExpressionCompare::parseExpression(&_expCtx, input, _expCtx.variablesParseState); - - auto expected = makeTagDisjunction(&_expCtx, toValues({{1}, {2}, {3}})); - - auto actual = _predicate.rewrite(inputExpr.get()); - - ASSERT_BSONOBJ_EQ(actual->serialize(false).getDocument().toBson(), - expected->serialize(false).getDocument().toBson()); - } - } } TEST_F(RangePredicateRewriteTest, AggRangeRewriteNoOp) { - { - auto input = fromjson(R"({$between: ["$age", {$literal: [1, 2, 3]}]})"); + auto ops = {"$gt", "$lt", "$gte", "$lte"}; + for (auto& op : ops) { + auto input = fromjson(str::stream() << "{" << op << ": [\"$age\", {$literal: [1, 2, 3]}]}"); auto inputExpr = - ExpressionBetween::parseExpression(&_expCtx, input, _expCtx.variablesParseState); + ExpressionCompare::parseExpression(&_expCtx, input, _expCtx.variablesParseState); auto expected = inputExpr; @@ -238,21 +206,6 @@ TEST_F(RangePredicateRewriteTest, AggRangeRewriteNoOp) { auto actual = _predicate.rewrite(inputExpr.get()); ASSERT(actual == nullptr); } - { - auto ops = {"$gt", "$lt", "$gte", "$lte"}; - for (auto& op : ops) { - auto input = - fromjson(str::stream() << "{" << op << ": [\"$age\", {$literal: [1, 2, 3]}]}"); - auto inputExpr = - ExpressionCompare::parseExpression(&_expCtx, input, _expCtx.variablesParseState); - - auto expected = inputExpr; - - _predicate.payloadValid = false; - auto actual = _predicate.rewrite(inputExpr.get()); - ASSERT(actual == nullptr); - } - } } BSONObj generateFFP(StringData path, int lb, int ub, int min, int max) { @@ -277,19 +230,6 @@ std::unique_ptr<MatchExpression> generateOpWithFFP(StringData path, int lb, int return std::make_unique<T>(path, ffp.firstElement()); } -std::unique_ptr<Expression> generateBetweenWithFFP(ExpressionContext* expCtx, - StringData path, - int lb, - int ub) { - auto ffp = Value(generateFFP(path, lb, ub, 0, 255).firstElement()); - auto ffpExpr = make_intrusive<ExpressionConstant>(expCtx, ffp); - auto fieldpath = ExpressionFieldPath::createPathFromString( - expCtx, path.toString(), expCtx->variablesParseState); - std::vector<boost::intrusive_ptr<Expression>> children = {std::move(fieldpath), - std::move(ffpExpr)}; - return std::make_unique<ExpressionBetween>(expCtx, std::move(children)); -} - std::unique_ptr<Expression> generateBetweenWithFFP( ExpressionContext* expCtx, ExpressionCompare::CmpOp op, StringData path, int lb, int ub) { auto ffp = Value(generateFFP(path, lb, ub, 0, 255).firstElement()); @@ -346,7 +286,6 @@ TEST_F(RangePredicateRewriteTest, CollScanRewriteMatch) { auto aggExpr = expr->getExpression(); \ ASSERT_BSONOBJ_EQ(aggExpr->serialize(false).getDocument().toBson(), expected); \ } - ASSERT_REWRITE_TO_INTERNAL_BETWEEN(BetweenMatchExpression); ASSERT_REWRITE_TO_INTERNAL_BETWEEN(GTMatchExpression); ASSERT_REWRITE_TO_INTERNAL_BETWEEN(GTEMatchExpression); ASSERT_REWRITE_TO_INTERNAL_BETWEEN(LTMatchExpression); @@ -388,24 +327,16 @@ TEST_F(RangePredicateRewriteTest, CollScanRewriteAgg) { } } })"); - { - auto input = generateBetweenWithFFP(&_expCtx, "age", 23, 35); + auto ops = {ExpressionCompare::GT, + ExpressionCompare::GTE, + ExpressionCompare::LT, + ExpressionCompare::LTE}; + for (auto& op : ops) { + auto input = generateBetweenWithFFP(&_expCtx, op, "age", 23, 35); auto result = _predicate.rewrite(input.get()); ASSERT(result); ASSERT_BSONOBJ_EQ(result->serialize(false).getDocument().toBson(), expected); } - { - auto ops = {ExpressionCompare::GT, - ExpressionCompare::GTE, - ExpressionCompare::LT, - ExpressionCompare::LTE}; - for (auto& op : ops) { - auto input = generateBetweenWithFFP(&_expCtx, op, "age", 23, 35); - auto result = _predicate.rewrite(input.get()); - ASSERT(result); - ASSERT_BSONOBJ_EQ(result->serialize(false).getDocument().toBson(), expected); - } - } } diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp index d2d60e2d49b..118f8f8c4fe 100644 --- a/src/mongo/db/query/sbe_stage_builder_expression.cpp +++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp @@ -349,7 +349,6 @@ public: void visit(const ExpressionDateToString* expr) final {} void visit(const ExpressionDateTrunc* expr) final {} void visit(const ExpressionDivide* expr) final {} - void visit(const ExpressionBetween* expr) final {} void visit(const ExpressionExp* expr) final {} void visit(const ExpressionFieldPath* expr) final {} void visit(const ExpressionFilter* expr) final { @@ -526,7 +525,6 @@ public: void visit(const ExpressionDateToString* expr) final {} void visit(const ExpressionDateTrunc*) final {} void visit(const ExpressionDivide* expr) final {} - void visit(const ExpressionBetween* expr) final {} void visit(const ExpressionExp* expr) final {} void visit(const ExpressionFieldPath* expr) final {} void visit(const ExpressionFilter* expr) final { @@ -1959,9 +1957,6 @@ public: _context->pushExpr( sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), std::move(expExpr))); } - void visit(const ExpressionBetween* expr) final { - unsupportedExpression("$_between"); - } void visit(const ExpressionFieldPath* expr) final { // There's a chance that we've already generated a SBE plan stage tree for this field path, // in which case we avoid regeneration of the same plan stage tree. diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp index b149e5eeda4..3df176979e7 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.cpp +++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp @@ -1180,9 +1180,6 @@ public: void visit(const WhereNoOpMatchExpression* expr) final { unsupportedExpression(expr); } - void visit(const BetweenMatchExpression* expr) final { - unsupportedExpression(expr); - } private: void unsupportedExpression(const MatchExpression* expr) const { @@ -1708,7 +1705,6 @@ public: } void visit(const WhereNoOpMatchExpression* expr) final {} - void visit(const BetweenMatchExpression* expr) final {} private: MatchExpressionVisitorContext* _context; @@ -1824,7 +1820,6 @@ public: void visit(const TypeMatchExpression* expr) final {} void visit(const WhereMatchExpression* expr) final {} void visit(const WhereNoOpMatchExpression* expr) final {} - void visit(const BetweenMatchExpression* expr) final {} private: MatchExpressionVisitorContext* _context; |