diff options
author | James Wahlin <james.wahlin@10gen.com> | 2017-01-12 17:44:52 -0500 |
---|---|---|
committer | James Wahlin <james.wahlin@10gen.com> | 2017-01-19 12:21:05 -0500 |
commit | 04b16905b7c3b6b3fce5fbc7f6ba17522311a7c4 (patch) | |
tree | 319ea5a70b9ffa0235666b9a35179b28fc8f90c6 /src | |
parent | 6a2af712f71774dae250c4cbe5f8ac695cfec3ea (diff) | |
download | mongo-04b16905b7c3b6b3fce5fbc7f6ba17522311a7c4.tar.gz |
SERVER-27649 $elemMatch serialization $regex support
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/matcher/expression_leaf.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_leaf.h | 2 | ||||
-rw-r--r-- | src/mongo/db/matcher/expression_serialization_test.cpp | 100 |
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(®exBob); + _regex->serializeToBSONTypeRegex(®exBob); 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'}"); |