summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavis Haupt <davis.haupt@mongodb.com>2022-11-11 18:16:45 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-11-11 19:43:06 +0000
commit016c6eb217c686732fb288e16e6c344ef6fea1f7 (patch)
treeceb2cf2a8ee561b90117f617dff7e3a33fe54e16
parent61dd3a14b837d1e9a9ac567a37245cbe7a9be6a5 (diff)
downloadmongo-016c6eb217c686732fb288e16e6c344ef6fea1f7.tar.gz
SERVER-71214 remove $between
-rw-r--r--jstests/core/between.js125
-rw-r--r--src/mongo/db/matcher/doc_validation_error.cpp6
-rw-r--r--src/mongo/db/matcher/expression.h1
-rw-r--r--src/mongo/db/matcher/expression_algo.cpp1
-rw-r--r--src/mongo/db/matcher/expression_leaf.cpp14
-rw-r--r--src/mongo/db/matcher/expression_leaf.h64
-rw-r--r--src/mongo/db/matcher/expression_leaf_test.cpp57
-rw-r--r--src/mongo/db/matcher/expression_parameterization.h1
-rw-r--r--src/mongo/db/matcher/expression_parser.cpp31
-rw-r--r--src/mongo/db/matcher/expression_parser.h1
-rw-r--r--src/mongo/db/matcher/expression_parser_test.cpp102
-rw-r--r--src/mongo/db/matcher/expression_visitor.h3
-rw-r--r--src/mongo/db/matcher/match_expression_dependencies.cpp4
-rw-r--r--src/mongo/db/pipeline/abt/agg_expression_visitor.cpp4
-rw-r--r--src/mongo/db/pipeline/abt/match_expression_visitor.cpp4
-rw-r--r--src/mongo/db/pipeline/document_source_match.cpp1
-rw-r--r--src/mongo/db/pipeline/expression.cpp7
-rw-r--r--src/mongo/db/pipeline/expression.h24
-rw-r--r--src/mongo/db/pipeline/expression_dependencies.cpp1
-rw-r--r--src/mongo/db/pipeline/expression_test.cpp29
-rw-r--r--src/mongo/db/pipeline/expression_visitor.h3
-rw-r--r--src/mongo/db/query/bind_input_params.cpp1
-rw-r--r--src/mongo/db/query/canonical_query_encoder.cpp3
-rw-r--r--src/mongo/db/query/cqf_command_utils.cpp4
-rw-r--r--src/mongo/db/query/fle/range_predicate.cpp85
-rw-r--r--src/mongo/db/query/fle/range_predicate.h2
-rw-r--r--src/mongo/db/query/fle/range_predicate_test.cpp93
-rw-r--r--src/mongo/db/query/sbe_stage_builder_expression.cpp5
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp5
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;