summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorReilly McBride <reilly.mcbride@mongodb.com>2022-08-05 20:25:47 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-05 21:35:30 +0000
commit94e93f4e95f7fa8ee169d493e50672b2c90bfc56 (patch)
treec7cdc28d3ca461800a96b8025b99c6afd3a4c8e7 /src/mongo/db
parent27ab971f2ab621d9b1d9804644b1b88befbc15bd (diff)
downloadmongo-94e93f4e95f7fa8ee169d493e50672b2c90bfc56.tar.gz
SERVER-67803 Parse $encryptedBetween MatchExpression
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/matcher/expression_parser.cpp8
-rw-r--r--src/mongo/db/matcher/expression_parser.h1
-rw-r--r--src/mongo/db/matcher/expression_parser_test.cpp78
-rw-r--r--src/mongo/db/pipeline/document_source_match.cpp1
4 files changed, 88 insertions, 0 deletions
diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp
index f3faa022c89..963ac06c634 100644
--- a/src/mongo/db/matcher/expression_parser.cpp
+++ b/src/mongo/db/matcher/expression_parser.cpp
@@ -1748,6 +1748,13 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
return {Status(ErrorCodes::BadValue,
str::stream() << "near must be first in: " << context)};
+ case PathAcceptingKeyword::ENCRYPTED_BETWEEN:
+ return std::make_unique<EncryptedBetweenMatchExpression>(
+ name,
+ e,
+ doc_validation_error::createAnnotation(
+ expCtx, e.fieldNameStringData().toString(), BSON(name << e.wrap())));
+
case PathAcceptingKeyword::INTERNAL_EXPR_EQ: {
if (e.type() == BSONType::Undefined || e.type() == BSONType::Array) {
return {Status(ErrorCodes::BadValue,
@@ -2144,6 +2151,7 @@ MONGO_INITIALIZER(MatchExpressionParser)(InitializerContext* context) {
{"bitsAnyClear", PathAcceptingKeyword::BITS_ANY_CLEAR},
{"bitsAnySet", PathAcceptingKeyword::BITS_ANY_SET},
{"elemMatch", PathAcceptingKeyword::ELEM_MATCH},
+ {"encryptedBetween", PathAcceptingKeyword::ENCRYPTED_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 101a7e10332..62e13814142 100644
--- a/src/mongo/db/matcher/expression_parser.h
+++ b/src/mongo/db/matcher/expression_parser.h
@@ -55,6 +55,7 @@ enum class PathAcceptingKeyword {
BITS_ANY_CLEAR,
BITS_ANY_SET,
ELEM_MATCH,
+ ENCRYPTED_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 00044cd8b23..34e5f594425 100644
--- a/src/mongo/db/matcher/expression_parser_test.cpp
+++ b/src/mongo/db/matcher/expression_parser_test.cpp
@@ -42,6 +42,7 @@
namespace mongo {
+
TEST(MatchExpressionParserTest, SimpleEQ1) {
BSONObj query = BSON("x" << 2);
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
@@ -809,4 +810,81 @@ TEST(InternalSchemaBinDataEncryptedTypeExpressionTest, NonBinDataValueDoesNotMat
BSONObj notMatch = BSON("a" << BSONArray());
ASSERT_FALSE(expr->matchesBSON(notMatch));
}
+
+TEST(EncryptedBetweenMatchExpressionTest, EncryptedBetweenExpectedBehaviorRHSNumeric) {
+ BSONObj query = BSON("a" << BSON("$encryptedBetween" << 5));
+ BSONObj inner = BSON("$encryptedBetween" << 5);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
+ ASSERT_TRUE(result.isOK());
+
+ ASSERT_EQ(result.getValue()->matchType(), MatchExpression::ENCRYPTED_BETWEEN);
+ auto ptr = result.getValue().get();
+ auto expr = static_cast<EncryptedBetweenMatchExpression*>(ptr);
+ ASSERT_BSONOBJ_EQ(expr->getSerializedRightHandSide(), inner);
+}
+
+TEST(EncryptedBetweenMatchExpressionTest, EncryptedBetweenExpectedBehaviorRHSDate) {
+ auto date = Date_t::now();
+ BSONObj query = BSON("a" << BSON("$encryptedBetween" << date));
+ BSONObj inner = BSON("$encryptedBetween" << date);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
+ ASSERT_TRUE(result.isOK());
+
+ ASSERT_EQ(result.getValue()->matchType(), MatchExpression::ENCRYPTED_BETWEEN);
+ auto ptr = result.getValue().get();
+ auto expr = static_cast<EncryptedBetweenMatchExpression*>(ptr);
+ ASSERT_BSONOBJ_EQ(expr->getSerializedRightHandSide(), inner);
+}
+
+TEST(EncryptedBetweenMatchExpressionTest, EncryptedBetweenExpectedBehaviorInsideAnd) {
+ BSONObj query = fromjson("{$and: [{x: 1}, {a: {$encryptedBetween: 5}}]}");
+ BSONObj inner = BSON("$encryptedBetween" << 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);
+ ASSERT_EQ(result.getValue()->getChild(0)->matchType(), MatchExpression::EQ);
+
+ auto ptr = result.getValue().get();
+ auto encryptedBetweenChild = ptr->getChild(1);
+ ASSERT_EQ(encryptedBetweenChild->matchType(), MatchExpression::ENCRYPTED_BETWEEN);
+
+ auto expr = static_cast<EncryptedBetweenMatchExpression*>(encryptedBetweenChild);
+ ASSERT_BSONOBJ_EQ(expr->getSerializedRightHandSide(), inner);
+}
+
+TEST(EncryptedBetweenMatchExpressionTest, EncryptedBetweenExpectedBehaviorInsideNot) {
+ BSONObj query = fromjson("{a: {$not: {$encryptedBetween: 5}}}");
+ BSONObj inner = BSON("$encryptedBetween" << 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().get();
+ auto encryptedBetweenChild = ptr->getChild(0)->getChild(0);
+ ASSERT_EQ(encryptedBetweenChild->matchType(), MatchExpression::ENCRYPTED_BETWEEN);
+ auto expr = static_cast<EncryptedBetweenMatchExpression*>(encryptedBetweenChild);
+ ASSERT_BSONOBJ_EQ(expr->getSerializedRightHandSide(), inner);
+}
+
+TEST(EncryptedBetweenMatchExpressionTest, EncryptedBetweenExpectedBehaviorDottedPath) {
+ BSONObj query = fromjson("{'a.b': {$encryptedBetween: 5}}");
+ BSONObj inner = BSON("$encryptedBetween" << 5);
+ boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
+ StatusWithMatchExpression result = MatchExpressionParser::parse(query, expCtx);
+ ASSERT_TRUE(result.isOK());
+ ASSERT_EQ(result.getValue()->path(), "a.b");
+
+ ASSERT_EQ(result.getValue()->matchType(), MatchExpression::ENCRYPTED_BETWEEN);
+ auto ptr = result.getValue().get();
+ auto expr = static_cast<EncryptedBetweenMatchExpression*>(ptr);
+ ASSERT_BSONOBJ_EQ(expr->getSerializedRightHandSide(), inner);
+}
+
} // namespace mongo
diff --git a/src/mongo/db/pipeline/document_source_match.cpp b/src/mongo/db/pipeline/document_source_match.cpp
index 038b38100c4..9a7ba486b30 100644
--- a/src/mongo/db/pipeline/document_source_match.cpp
+++ b/src/mongo/db/pipeline/document_source_match.cpp
@@ -266,6 +266,7 @@ Document redactSafePortionDollarOps(BSONObj expr) {
}
// These are never allowed
+ case PathAcceptingKeyword::ENCRYPTED_BETWEEN:
case PathAcceptingKeyword::EXISTS:
case PathAcceptingKeyword::GEO_INTERSECTS:
case PathAcceptingKeyword::GEO_NEAR: