summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames Wahlin <james.wahlin@10gen.com>2017-01-12 17:44:52 -0500
committerJames Wahlin <james.wahlin@10gen.com>2017-01-19 12:21:05 -0500
commit04b16905b7c3b6b3fce5fbc7f6ba17522311a7c4 (patch)
tree319ea5a70b9ffa0235666b9a35179b28fc8f90c6 /src
parent6a2af712f71774dae250c4cbe5f8ac695cfec3ea (diff)
downloadmongo-04b16905b7c3b6b3fce5fbc7f6ba17522311a7c4.tar.gz
SERVER-27649 $elemMatch serialization $regex support
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/matcher/expression_leaf.cpp13
-rw-r--r--src/mongo/db/matcher/expression_leaf.h2
-rw-r--r--src/mongo/db/matcher/expression_serialization_test.cpp100
3 files changed, 105 insertions, 10 deletions
diff --git a/src/mongo/db/matcher/expression_leaf.cpp b/src/mongo/db/matcher/expression_leaf.cpp
index 90b0cc985dc..d562bff141e 100644
--- a/src/mongo/db/matcher/expression_leaf.cpp
+++ b/src/mongo/db/matcher/expression_leaf.cpp
@@ -319,6 +319,17 @@ void RegexMatchExpression::debugString(StringBuilder& debug, int level) const {
}
void RegexMatchExpression::serialize(BSONObjBuilder* out) const {
+ BSONObjBuilder regexBuilder(out->subobjStart(path()));
+ regexBuilder.append("$regex", _regex);
+
+ if (!_flags.empty()) {
+ regexBuilder.append("$options", _flags);
+ }
+
+ regexBuilder.doneFast();
+}
+
+void RegexMatchExpression::serializeToBSONTypeRegex(BSONObjBuilder* out) const {
out->appendRegex(path(), _regex, _flags);
}
@@ -596,7 +607,7 @@ void InMatchExpression::serialize(BSONObjBuilder* out) const {
}
for (auto&& _regex : _regexes) {
BSONObjBuilder regexBob;
- _regex->serialize(&regexBob);
+ _regex->serializeToBSONTypeRegex(&regexBob);
arrBob.append(regexBob.obj().firstElement());
}
arrBob.doneFast();
diff --git a/src/mongo/db/matcher/expression_leaf.h b/src/mongo/db/matcher/expression_leaf.h
index 26568b20b81..128d3070737 100644
--- a/src/mongo/db/matcher/expression_leaf.h
+++ b/src/mongo/db/matcher/expression_leaf.h
@@ -247,6 +247,8 @@ public:
virtual void serialize(BSONObjBuilder* out) const;
+ void serializeToBSONTypeRegex(BSONObjBuilder* out) const;
+
void shortDebugString(StringBuilder& debug) const;
virtual bool equivalent(const MatchExpression* other) const;
diff --git a/src/mongo/db/matcher/expression_serialization_test.cpp b/src/mongo/db/matcher/expression_serialization_test.cpp
index 572ae25d585..13a2aaa172d 100644
--- a/src/mongo/db/matcher/expression_serialization_test.cpp
+++ b/src/mongo/db/matcher/expression_serialization_test.cpp
@@ -166,6 +166,28 @@ TEST(SerializeBasic, ExpressionElemMatchValueSerializesCorrectly) {
ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
}
+TEST(SerializeBasic, ExpressionElemMatchValueWithRegexSerializesCorrectly) {
+ const CollatorInterface* collator = nullptr;
+ const auto match = BSON("x" << BSON("$elemMatch" << BSON("$regex"
+ << "abc"
+ << "$options"
+ << "i")));
+ Matcher original(match, ExtensionsCallbackNoop(), collator);
+ Matcher reserialized(
+ serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), match);
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
+
+ BSONObj obj = fromjson("{x: ['abc', 'xyz']}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+
+ obj = fromjson("{x: ['ABC', 'XYZ']}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+
+ obj = fromjson("{x: ['def', 'xyz']}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+}
+
TEST(SerializeBasic, ExpressionElemMatchValueWithEmptyStringSerializesCorrectly) {
const CollatorInterface* collator = nullptr;
Matcher original(
@@ -233,7 +255,12 @@ TEST(SerializeBasic, ExpressionAllWithRegex) {
fromjson("{x: {$all: [/a.b.c/, /.d.e./]}}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$and: [{x: /a.b.c/}, {x: /.d.e./}]}"));
+
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("$and" << BSON_ARRAY(BSON("x" << BSON("$regex"
+ << "a.b.c"))
+ << BSON("x" << BSON("$regex"
+ << ".d.e.")))));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abcde'}");
@@ -276,6 +303,26 @@ TEST(SerializeBasic, ExpressionNeSerializesCorrectly) {
ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
}
+TEST(SerializeBasic, ExpressionNeWithRegexObjectSerializesCorrectly) {
+ const CollatorInterface* collator = nullptr;
+ Matcher original(BSON("x" << BSON("$ne" << BSON("$regex"
+ << "abc"))),
+ ExtensionsCallbackNoop(),
+ collator);
+ Matcher reserialized(
+ serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$eq" << BSON("$regex"
+ << "abc"))))));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
+
+ BSONObj obj = fromjson("{x: {a: 1}}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+
+ obj = fromjson("{x: {a: [1, 2]}}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+}
+
TEST(SerializeBasic, ExpressionLtSerializesCorrectly) {
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{x: {$lt: 3}}"), ExtensionsCallbackNoop(), collator);
@@ -341,7 +388,9 @@ TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
Matcher original(fromjson("{x: {$regex: 'a.b'}}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$regex: 'a.b'}}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("x" << BSON("$regex"
+ << "a.b")));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");
@@ -351,12 +400,16 @@ TEST(SerializeBasic, ExpressionRegexWithObjSerializesCorrectly) {
ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
}
-TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
+TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{x: /a.b/i}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$regex: 'a.b', $options: 'i'}}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("x" << BSON("$regex"
+ << "a.b"
+ << "$options"
+ << "i")));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");
@@ -366,12 +419,14 @@ TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
}
-TEST(SerializeBasic, ExpressionRegexWithValueAndOptionsSerializesCorrectly) {
+TEST(SerializeBasic, ExpressionRegexWithValueSerializesCorrectly) {
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{x: /a.b/}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{x: {$regex: 'a.b'}}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("x" << BSON("$regex"
+ << "a.b")));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");
@@ -510,6 +565,25 @@ TEST(SerializeBasic, ExpressionNinSerializesCorrectly) {
ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
}
+TEST(SerializeBasic, ExpressionNinWithRegexValueSerializesCorrectly) {
+ const CollatorInterface* collator = nullptr;
+ Matcher original(
+ fromjson("{x: {$nin: [/abc/, /def/, /xyz/]}}"), ExtensionsCallbackNoop(), collator);
+ Matcher reserialized(
+ serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ fromjson("{$nor: [{x: {$in: [/abc/, /def/, /xyz/]}}]}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
+
+ BSONObj obj = fromjson("{x: 'abc'}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+
+ obj = fromjson("{x: 'def'}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+ obj = fromjson("{x: [/abc/, /def/]}");
+ ASSERT_EQ(original.matches(obj), reserialized.matches(obj));
+}
+
TEST(SerializeBasic, ExpressionBitsAllSetSerializesCorrectly) {
const CollatorInterface* collator = nullptr;
Matcher original(fromjson("{x: {$bitsAllSet: [1, 3]}}"), ExtensionsCallbackNoop(), collator);
@@ -626,7 +700,9 @@ TEST(SerializeBasic, ExpressionNotWithRegexObjSerializesCorrectly) {
Matcher original(fromjson("{x: {$not: {$regex: 'a.b'}}}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: /a.b/}]}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
+ << "a.b")))));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");
@@ -641,7 +717,9 @@ TEST(SerializeBasic, ExpressionNotWithRegexValueSerializesCorrectly) {
Matcher original(fromjson("{x: {$not: /a.b/}}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: /a.b/}]}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
+ << "a.b")))));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");
@@ -656,7 +734,11 @@ TEST(SerializeBasic, ExpressionNotWithRegexValueAndOptionsSerializesCorrectly) {
Matcher original(fromjson("{x: {$not: /a.b/i}}"), ExtensionsCallbackNoop(), collator);
Matcher reserialized(
serialize(original.getMatchExpression()), ExtensionsCallbackNoop(), collator);
- ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), fromjson("{$nor: [{x: /a.b/i}]}"));
+ ASSERT_BSONOBJ_EQ(*reserialized.getQuery(),
+ BSON("$nor" << BSON_ARRAY(BSON("x" << BSON("$regex"
+ << "a.b"
+ << "$options"
+ << "i")))));
ASSERT_BSONOBJ_EQ(*reserialized.getQuery(), serialize(reserialized.getMatchExpression()));
BSONObj obj = fromjson("{x: 'abc'}");