summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorNikita Lapkov <nikita.lapkov@mongodb.com>2021-02-25 12:13:12 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-03-01 19:25:51 +0000
commitf7d172d0decc6128b6ce497357bbf0ff0e676355 (patch)
tree018d07884f5a7e876d84aedab69b6270183f2197 /src/mongo/db
parent4b95014f05755a197d81f97879a24c9a6e5c535d (diff)
downloadmongo-f7d172d0decc6128b6ce497357bbf0ff0e676355.tar.gz
SERVER-54493 Support BSONType::RegEx values in $regex match expression in SBE
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/exec/sbe/values/value.cpp22
-rw-r--r--src/mongo/db/exec/sbe/values/value.h2
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.h5
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp26
4 files changed, 43 insertions, 12 deletions
diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp
index 52f49ede825..11fdac4f871 100644
--- a/src/mongo/db/exec/sbe/values/value.cpp
+++ b/src/mongo/db/exec/sbe/values/value.cpp
@@ -45,9 +45,25 @@ namespace sbe {
namespace value {
std::pair<TypeTags, Value> makeCopyBsonRegex(const BsonRegex& regex) {
- auto buffer = new char[regex.byteSize()];
- memcpy(buffer, regex.data(), regex.byteSize());
- return {TypeTags::bsonRegex, bitcastFrom<char*>(buffer)};
+ auto buffer = std::make_unique<char[]>(regex.byteSize());
+ memcpy(buffer.get(), regex.data(), regex.byteSize());
+ return {TypeTags::bsonRegex, bitcastFrom<char*>(buffer.release())};
+}
+
+std::pair<TypeTags, Value> makeNewBsonRegex(std::string_view pattern, std::string_view flags) {
+ // Add 2 to account NULL bytes after pattern and flags.
+ auto totalSize = pattern.size() + flags.size() + 2;
+ auto buffer = std::make_unique<char[]>(totalSize);
+ auto rawBuffer = buffer.get();
+
+ // Copy pattern first and flags after it.
+ memcpy(rawBuffer, pattern.data(), pattern.size());
+ memcpy(rawBuffer + pattern.size() + 1, flags.data(), flags.size());
+
+ // Ensure NULL byte is placed after each part.
+ rawBuffer[pattern.size()] = '\0';
+ rawBuffer[totalSize - 1] = '\0';
+ return {TypeTags::bsonRegex, bitcastFrom<char*>(buffer.release())};
}
std::pair<TypeTags, Value> makeCopyBsonJavascript(std::string_view code) {
diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h
index 86f1ebef155..d24fe5b2bae 100644
--- a/src/mongo/db/exec/sbe/values/value.h
+++ b/src/mongo/db/exec/sbe/values/value.h
@@ -947,6 +947,8 @@ inline BsonRegex getBsonRegexView(Value val) noexcept {
std::pair<TypeTags, Value> makeCopyBsonRegex(const BsonRegex& regex);
+std::pair<TypeTags, Value> makeNewBsonRegex(std::string_view pattern, std::string_view flags);
+
inline std::string_view getBsonJavascriptView(Value val) noexcept {
return getStringView(TypeTags::StringBig, val);
}
diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h
index 5dfe25cc536..7a51732a972 100644
--- a/src/mongo/db/exec/sbe/vm/vm.h
+++ b/src/mongo/db/exec/sbe/vm/vm.h
@@ -127,6 +127,11 @@ std::pair<value::TypeTags, value::Value> genericCompare(
auto threeWayResult = memcmp(lhsObjId, rhsObjId, sizeof(value::ObjectIdType));
auto booleanResult = op(threeWayResult, 0);
return {value::TypeTags::Boolean, value::bitcastFrom<bool>(booleanResult)};
+ } else if (lhsTag == value::TypeTags::bsonRegex && rhsTag == value::TypeTags::bsonRegex) {
+ auto lhsRegex = value::getBsonRegexView(lhsValue);
+ auto rhsRegex = value::getBsonRegexView(rhsValue);
+ auto result = op(lhsRegex.dataView(), rhsRegex.dataView());
+ return {value::TypeTags::Boolean, value::bitcastFrom<bool>(result)};
}
return {value::TypeTags::Nothing, 0};
diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp
index 8f5d9b36b55..6b44d54063b 100644
--- a/src/mongo/db/query/sbe_stage_builder_filter.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp
@@ -1541,16 +1541,24 @@ public:
void visit(const RegexMatchExpression* expr) final {
auto makePredicate = [expr](sbe::value::SlotId inputSlot,
EvalStage inputStage) -> EvalExprStagePair {
- auto [regexTag, regexVal] =
+ auto [bsonRegexTag, bsonRegexVal] =
+ sbe::value::makeNewBsonRegex(expr->getString(), expr->getFlags());
+ auto [compiledRegexTag, compiledRegexVal] =
sbe::value::makeNewPcreRegex(expr->getString(), expr->getFlags());
- // TODO: In the future, this needs to account for the fact that the regex match
- // expression matches strings, but also matches stored regexes. For example,
- // {$match: {a: /foo/}} matches the document {a: /foo/} in addition to {a: "foobar"}.
- return {makeFillEmptyFalse(sbe::makeE<sbe::EFunction>(
- "regexMatch",
- sbe::makeEs(sbe::makeE<sbe::EConstant>(regexTag, regexVal),
- sbe::makeE<sbe::EVariable>(inputSlot)))),
- std::move(inputStage)};
+ // TODO SERVER-54837: Support BSONType::Symbol once it is added to SBE.
+ sbe::EVariable inputVar{inputSlot};
+ auto resultExpr = makeBinaryOp(
+ sbe::EPrimBinary::logicOr,
+ makeFillEmptyFalse(
+ makeBinaryOp(sbe::EPrimBinary::eq,
+ inputVar.clone(),
+ sbe::makeE<sbe::EConstant>(bsonRegexTag, bsonRegexVal))),
+ makeFillEmptyFalse(
+ makeFunction("regexMatch",
+ sbe::makeE<sbe::EConstant>(compiledRegexTag, compiledRegexVal),
+ inputVar.clone())));
+
+ return {std::move(resultExpr), std::move(inputStage)};
};
generatePredicate(_context, expr->fieldRef(), std::move(makePredicate));