From 9c2fa2cdee7dfeee33760f40e80c53e5938faffe Mon Sep 17 00:00:00 2001 From: XueruiFa Date: Fri, 19 Mar 2021 14:16:47 +0000 Subject: Revert "SERVER-55180 Convert SBE from std::string_view to StringData" This reverts commit b0e48211b3cbda845bd18c3283fe0d5f5dcd98c6. --- src/mongo/base/string_data.h | 18 +++++ src/mongo/db/exec/sbe/expressions/expression.h | 6 +- .../db/exec/sbe/expressions/sbe_concat_test.cpp | 3 +- .../db/exec/sbe/expressions/sbe_regex_test.cpp | 7 +- src/mongo/db/exec/sbe/parser/parser.cpp | 4 +- src/mongo/db/exec/sbe/sbe_filter_test.cpp | 3 +- src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp | 3 +- src/mongo/db/exec/sbe/sbe_hash_join_test.cpp | 1 + src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp | 1 + src/mongo/db/exec/sbe/sbe_sort_test.cpp | 1 + src/mongo/db/exec/sbe/sbe_sorted_merge_test.cpp | 1 + src/mongo/db/exec/sbe/sbe_test.cpp | 25 +++---- src/mongo/db/exec/sbe/sbe_unique_test.cpp | 1 + src/mongo/db/exec/sbe/stages/ix_scan.cpp | 2 +- src/mongo/db/exec/sbe/stages/ix_scan.h | 2 +- src/mongo/db/exec/sbe/util/debug_print.cpp | 12 ++-- src/mongo/db/exec/sbe/util/debug_print.h | 8 +-- src/mongo/db/exec/sbe/values/bson.cpp | 14 ++-- src/mongo/db/exec/sbe/values/bson.h | 4 +- src/mongo/db/exec/sbe/values/slot.h | 2 +- src/mongo/db/exec/sbe/values/value.cpp | 83 ++++++++++------------ src/mongo/db/exec/sbe/values/value.h | 53 +++++++------- .../sbe/values/value_serialize_for_sorter_test.cpp | 10 +-- src/mongo/db/exec/sbe/vm/datetime.cpp | 6 +- src/mongo/db/exec/sbe/vm/vm.cpp | 64 ++++++++++------- src/mongo/db/exec/sbe/vm/vm.h | 6 +- src/mongo/db/pipeline/expression.cpp | 13 +++- src/mongo/db/query/sbe_stage_builder.cpp | 27 ++++--- .../db/query/sbe_stage_builder_expression.cpp | 34 ++++----- src/mongo/db/query/sbe_stage_builder_filter.cpp | 4 +- src/mongo/db/query/sbe_stage_builder_helpers.cpp | 16 +++-- src/mongo/db/query/sbe_stage_builder_helpers.h | 4 +- .../db/query/sbe_stage_builder_index_scan.cpp | 18 ++--- .../db/query/sbe_stage_builder_projection.cpp | 20 +++--- 34 files changed, 269 insertions(+), 207 deletions(-) diff --git a/src/mongo/base/string_data.h b/src/mongo/base/string_data.h index eb762771a77..bc2ee4ffc36 100644 --- a/src/mongo/base/string_data.h +++ b/src/mongo/base/string_data.h @@ -89,6 +89,12 @@ public: */ StringData(const std::string& s) : StringData(s.data(), s.length(), TrustedInitTag()) {} + /** + * Implicitly convert a std::string_view to a StringData. We can use the trusted + * init path because string_view::data() points to length() bytes of data. + */ + StringData(std::string_view s) : StringData(s.data(), s.length(), TrustedInitTag()) {} + /** * Constructs a StringData with an explicit length. 'c' must * either be nullptr (in which case len must be zero), or be a @@ -105,6 +111,18 @@ public: return toString(); } + /** + * Implicitly convert to a std::string_view. + */ + operator std::string_view() const { + // std::string_view produces undefined behaviour if [pointer, pointer + size) is not a valid + // range. To fix this we explicitly use default constructor if StringData contains nullptr. + if (MONGO_unlikely(rawData() == nullptr)) { + return {}; + } + return {rawData(), size()}; + } + /** * Constructs a StringData with begin and end iterators. begin points to the beginning of the * string. end points to the position past the end of the string. In a null-terminated string, diff --git a/src/mongo/db/exec/sbe/expressions/expression.h b/src/mongo/db/exec/sbe/expressions/expression.h index f52acef32ca..4e811337cc3 100644 --- a/src/mongo/db/exec/sbe/expressions/expression.h +++ b/src/mongo/db/exec/sbe/expressions/expression.h @@ -317,7 +317,7 @@ auto makeSV(Args&&... args) { class EConstant final : public EExpression { public: EConstant(value::TypeTags tag, value::Value val) : _tag(tag), _val(val) {} - EConstant(StringData str) { + EConstant(std::string_view str) { // Views are non-owning so we have to make a copy. std::tie(_tag, _val) = value::makeNewString(str); } @@ -448,7 +448,7 @@ private: */ class EFunction final : public EExpression { public: - EFunction(StringData name, std::vector> args) : _name(name) { + EFunction(std::string_view name, std::vector> args) : _name(name) { _nodes = std::move(args); validateNodes(); } @@ -513,7 +513,7 @@ private: */ class EFail final : public EExpression { public: - EFail(ErrorCodes::Error code, StringData message) : _code(code) { + EFail(ErrorCodes::Error code, std::string_view message) : _code(code) { std::tie(_messageTag, _messageVal) = value::makeNewString(message); } diff --git a/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp index 4275ae03eee..857704fb5b5 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_concat_test.cpp @@ -33,7 +33,8 @@ namespace mongo::sbe { class SBEConcatTest : public EExpressionTestFixture { protected: - void runAndAssertExpression(const vm::CodeFragment* compiledExpr, StringData expectedVal) { + void runAndAssertExpression(const vm::CodeFragment* compiledExpr, + std::string_view expectedVal) { auto [tag, val] = runCompiledExpression(compiledExpr); value::ValueGuard guard(tag, val); diff --git a/src/mongo/db/exec/sbe/expressions/sbe_regex_test.cpp b/src/mongo/db/exec/sbe/expressions/sbe_regex_test.cpp index 8486a7c65f8..2e3c87789cb 100644 --- a/src/mongo/db/exec/sbe/expressions/sbe_regex_test.cpp +++ b/src/mongo/db/exec/sbe/expressions/sbe_regex_test.cpp @@ -32,7 +32,8 @@ namespace mongo::sbe { class SBERegexTest : public EExpressionTestFixture { protected: - void runAndAssertRegexCompile(const vm::CodeFragment* compiledExpr, StringData regexString) { + void runAndAssertRegexCompile(const vm::CodeFragment* compiledExpr, + std::string_view regexString) { auto [tag, val] = runCompiledExpression(compiledExpr); value::ValueGuard guard(tag, val); @@ -52,7 +53,7 @@ protected: } void runAndAssertFindExpression(const vm::CodeFragment* compiledExpr, - StringData expectedMatch, + std::string_view expectedMatch, int idx) { auto [tag, val] = runCompiledExpression(compiledExpr); value::ValueGuard guard(tag, val); @@ -71,7 +72,7 @@ protected: ASSERT_EQUALS(value::numericCast(idxTag, idxVal), idx); } - void addMatchResult(value::Array* arrayPtr, StringData matchStr, int32_t idx) { + void addMatchResult(value::Array* arrayPtr, std::string_view matchStr, int32_t idx) { auto [objTag, objVal] = value::makeNewObject(); value::ValueGuard objGuard{objTag, objVal}; auto obj = value::getObjectView(objVal); diff --git a/src/mongo/db/exec/sbe/parser/parser.cpp b/src/mongo/db/exec/sbe/parser/parser.cpp index a426b9d9a8d..19fe41378ef 100644 --- a/src/mongo/db/exec/sbe/parser/parser.cpp +++ b/src/mongo/db/exec/sbe/parser/parser.cpp @@ -1161,7 +1161,7 @@ std::unique_ptr Parser::walkPathValue(AstQuery& ast, std::move(inputStage), getCurrentPlanNodeId(), outputSlot, - makeE("getField"_sd, + makeE("getField"sv, makeEs(makeE(inputSlot), makeE(ast.nodes[0]->identifier)))); } @@ -1172,7 +1172,7 @@ std::unique_ptr Parser::walkPathValue(AstQuery& ast, makeProjectStage(std::move(inputStage), getCurrentPlanNodeId(), traverseIn, - makeE("getField"_sd, + makeE("getField"sv, makeEs(makeE(inputSlot), makeE(ast.nodes[0]->identifier)))); auto in = makeS( diff --git a/src/mongo/db/exec/sbe/sbe_filter_test.cpp b/src/mongo/db/exec/sbe/sbe_filter_test.cpp index 15a34975c9f..eb7c7c05214 100644 --- a/src/mongo/db/exec/sbe/sbe_filter_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_filter_test.cpp @@ -33,6 +33,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/filter.h" @@ -147,7 +148,7 @@ TEST_F(FilterStageTest, FilterIsNumberTest) { // Build a FilterStage whose filter expression is "isNumber(scanSlot)". auto filter = makeS>( std::move(scanStage), - makeE("isNumber"_sd, makeEs(makeE(scanSlot))), + makeE("isNumber"sv, makeEs(makeE(scanSlot))), kEmptyPlanNodeId); return std::make_pair(scanSlot, std::move(filter)); diff --git a/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp b/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp index 2c3bd3d335d..281a7cf0684 100644 --- a/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_hash_agg_test.cpp @@ -33,6 +33,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/hash_agg.h" @@ -114,7 +115,7 @@ TEST_F(HashAggStageTest, HashAggAddToSetTest) { auto [expectedTag, expectedVal] = value::makeNewArray(); value::ValueGuard expectedGuard{expectedTag, expectedVal}; - for (auto&& sv : std::array{"Aa", "BB", "cc", "dD"}) { + for (auto&& sv : std::array{"Aa", "BB", "cc", "dD"}) { auto [tag, val] = value::makeNewString(sv); value::getArrayView(expectedVal)->push_back(tag, val); } diff --git a/src/mongo/db/exec/sbe/sbe_hash_join_test.cpp b/src/mongo/db/exec/sbe/sbe_hash_join_test.cpp index fc9b18a2fdc..956831cc8e0 100644 --- a/src/mongo/db/exec/sbe/sbe_hash_join_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_hash_join_test.cpp @@ -33,6 +33,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/hash_join.h" diff --git a/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp b/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp index 0782f0bdc42..473ffbe5510 100644 --- a/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_plan_stage_test.cpp @@ -36,6 +36,7 @@ #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" +#include #include "mongo/logv2/log.h" diff --git a/src/mongo/db/exec/sbe/sbe_sort_test.cpp b/src/mongo/db/exec/sbe/sbe_sort_test.cpp index 83b59daa535..1d4574f2d50 100644 --- a/src/mongo/db/exec/sbe/sbe_sort_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_sort_test.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/sort.h" diff --git a/src/mongo/db/exec/sbe/sbe_sorted_merge_test.cpp b/src/mongo/db/exec/sbe/sbe_sorted_merge_test.cpp index 009106f8c59..37cad8d4532 100644 --- a/src/mongo/db/exec/sbe/sbe_sorted_merge_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_sorted_merge_test.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/sorted_merge.h" diff --git a/src/mongo/db/exec/sbe/sbe_test.cpp b/src/mongo/db/exec/sbe/sbe_test.cpp index ad7529e96bd..74460db8e2c 100644 --- a/src/mongo/db/exec/sbe/sbe_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_test.cpp @@ -35,15 +35,16 @@ namespace mongo::sbe { TEST(SBEValues, Basic) { + using namespace std::literals; { - const auto [tag, val] = value::makeNewString("small"_sd); + const auto [tag, val] = value::makeNewString("small"sv); ASSERT_EQUALS(tag, value::TypeTags::StringSmall); value::releaseValue(tag, val); } { - const auto [tag, val] = value::makeNewString("not so small string"_sd); + const auto [tag, val] = value::makeNewString("not so small string"sv); ASSERT_EQUALS(tag, value::TypeTags::StringBig); value::releaseValue(tag, val); @@ -52,11 +53,11 @@ TEST(SBEValues, Basic) { const auto [tag, val] = value::makeNewObject(); auto obj = value::getObjectView(val); - const auto [fieldTag, fieldVal] = value::makeNewString("not so small string"_sd); - obj->push_back("field"_sd, fieldTag, fieldVal); + const auto [fieldTag, fieldVal] = value::makeNewString("not so small string"sv); + obj->push_back("field"sv, fieldTag, fieldVal); ASSERT_EQUALS(obj->size(), 1); - const auto [checkTag, checkVal] = obj->getField("field"_sd); + const auto [checkTag, checkVal] = obj->getField("field"sv); ASSERT_EQUALS(fieldTag, checkTag); ASSERT_EQUALS(fieldVal, checkVal); @@ -67,7 +68,7 @@ TEST(SBEValues, Basic) { const auto [tag, val] = value::makeNewArray(); auto obj = value::getArrayView(val); - const auto [fieldTag, fieldVal] = value::makeNewString("not so small string"_sd); + const auto [fieldTag, fieldVal] = value::makeNewString("not so small string"sv); obj->push_back(fieldTag, fieldVal); ASSERT_EQUALS(obj->size(), 1); @@ -197,15 +198,15 @@ TEST(SBEValues, HashCompound) { { auto [tag1, val1] = value::makeNewObject(); auto obj1 = value::getObjectView(val1); - obj1->push_back("a"_sd, value::TypeTags::NumberInt32, value::bitcastFrom(-5)); - obj1->push_back("b"_sd, value::TypeTags::NumberInt32, value::bitcastFrom(-6)); - obj1->push_back("c"_sd, value::TypeTags::NumberInt32, value::bitcastFrom(-7)); + obj1->push_back("a"sv, value::TypeTags::NumberInt32, value::bitcastFrom(-5)); + obj1->push_back("b"sv, value::TypeTags::NumberInt32, value::bitcastFrom(-6)); + obj1->push_back("c"sv, value::TypeTags::NumberInt32, value::bitcastFrom(-7)); auto [tag2, val2] = value::makeNewObject(); auto obj2 = value::getObjectView(val2); - obj2->push_back("a"_sd, value::TypeTags::NumberDouble, value::bitcastFrom(-5.0)); - obj2->push_back("b"_sd, value::TypeTags::NumberDouble, value::bitcastFrom(-6.0)); - obj2->push_back("c"_sd, value::TypeTags::NumberDouble, value::bitcastFrom(-7.0)); + obj2->push_back("a"sv, value::TypeTags::NumberDouble, value::bitcastFrom(-5.0)); + obj2->push_back("b"sv, value::TypeTags::NumberDouble, value::bitcastFrom(-6.0)); + obj2->push_back("c"sv, value::TypeTags::NumberDouble, value::bitcastFrom(-7.0)); ASSERT_EQUALS(value::hashValue(tag1, val1), value::hashValue(tag2, val2)); diff --git a/src/mongo/db/exec/sbe/sbe_unique_test.cpp b/src/mongo/db/exec/sbe/sbe_unique_test.cpp index 812b7383b1e..08ed98c1723 100644 --- a/src/mongo/db/exec/sbe/sbe_unique_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_unique_test.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" +#include #include "mongo/db/exec/sbe/sbe_plan_stage_test.h" #include "mongo/db/exec/sbe/stages/unique.h" diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp index 8e70ccd2004..854af856cd2 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp +++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp @@ -39,7 +39,7 @@ namespace mongo::sbe { IndexScanStage::IndexScanStage(CollectionUUID collUuid, - StringData indexName, + std::string_view indexName, bool forward, boost::optional recordSlot, boost::optional recordIdSlot, diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.h b/src/mongo/db/exec/sbe/stages/ix_scan.h index 63c583764ab..da10c9bf126 100644 --- a/src/mongo/db/exec/sbe/stages/ix_scan.h +++ b/src/mongo/db/exec/sbe/stages/ix_scan.h @@ -60,7 +60,7 @@ namespace mongo::sbe { class IndexScanStage final : public PlanStage { public: IndexScanStage(CollectionUUID collUuid, - StringData indexName, + std::string_view indexName, bool forward, boost::optional recordSlot, boost::optional recordIdSlot, diff --git a/src/mongo/db/exec/sbe/util/debug_print.cpp b/src/mongo/db/exec/sbe/util/debug_print.cpp index e3d831b5ab5..939779be8de 100644 --- a/src/mongo/db/exec/sbe/util/debug_print.cpp +++ b/src/mongo/db/exec/sbe/util/debug_print.cpp @@ -92,20 +92,20 @@ std::string DebugPrinter::print(const std::vector& blocks) { break; } - StringData sv(b.str); + std::string_view sv(b.str); if (!sv.empty()) { - if (*sv.begin() == '`') { - sv = sv.substr(1); + if (sv.front() == '`') { + sv.remove_prefix(1); if (!ret.empty() && ret.back() == ' ') { ret.resize(ret.size() - 1, 0); } } - if (!sv.empty() && *(sv.end() - 1) == '`') { - sv = sv.substr(0, sv.size() - 1); + if (!sv.empty() && sv.back() == '`') { + sv.remove_suffix(1); addSpace = false; } if (!sv.empty()) { - ret.append(sv.begin(), sv.end()); + ret.append(sv); if (addSpace) { ret.append(" "); } diff --git a/src/mongo/db/exec/sbe/util/debug_print.h b/src/mongo/db/exec/sbe/util/debug_print.h index a11bb24c75c..19e29d7bdf4 100644 --- a/src/mongo/db/exec/sbe/util/debug_print.h +++ b/src/mongo/db/exec/sbe/util/debug_print.h @@ -60,16 +60,16 @@ public: Command cmd; std::string str; - Block(StringData s) : cmd(cmdNone), str(s) {} + Block(std::string_view s) : cmd(cmdNone), str(s) {} - Block(Command c, StringData s) : cmd(c), str(s) {} + Block(Command c, std::string_view s) : cmd(c), str(s) {} Block(Command c) : cmd(c) {} }; DebugPrinter(bool colorConsole = false) : _colorConsole(colorConsole) {} - static void addKeyword(std::vector& ret, StringData k) { + static void addKeyword(std::vector& ret, std::string_view k) { ret.emplace_back(Block::cmdColorCyan); ret.emplace_back(Block{Block::cmdNoneNoSpace, k}); ret.emplace_back(Block::cmdColorNone); @@ -92,7 +92,7 @@ public: ret.emplace_back(Block{Block::cmdNoneNoSpace, " "}); } - static void addIdentifier(std::vector& ret, StringData k) { + static void addIdentifier(std::vector& ret, std::string_view k) { ret.emplace_back(Block::cmdColorGreen); ret.emplace_back(Block{Block::cmdNoneNoSpace, k}); ret.emplace_back(Block::cmdColorNone); diff --git a/src/mongo/db/exec/sbe/values/bson.cpp b/src/mongo/db/exec/sbe/values/bson.cpp index 6a67127bd6f..ea5f50b7e58 100644 --- a/src/mongo/db/exec/sbe/values/bson.cpp +++ b/src/mongo/db/exec/sbe/values/bson.cpp @@ -290,7 +290,8 @@ void convertToBsonObj(ArrayBuilder& builder, value::ArrayEnumerator arr) { case value::TypeTags::StringSmall: case value::TypeTags::StringBig: case value::TypeTags::bsonString: { - builder.append(value::getStringView(tag, val)); + auto sv = value::getStringView(tag, val); + builder.append(StringData{sv.data(), sv.size()}); break; } case value::TypeTags::Array: { @@ -384,9 +385,11 @@ template void convertToBsonObj(UniqueBSONObjBuilder& build template void appendValueToBsonObj(ObjBuilder& builder, - StringData name, + std::string_view nameSV, value::TypeTags tag, value::Value val) { + StringData name{nameSV.data(), nameSV.size()}; + switch (tag) { case value::TypeTags::Nothing: break; @@ -418,7 +421,8 @@ void appendValueToBsonObj(ObjBuilder& builder, case value::TypeTags::StringSmall: case value::TypeTags::StringBig: case value::TypeTags::bsonString: { - builder.append(name, value::getStringView(tag, val)); + auto sv = value::getStringView(tag, val); + builder.append(name, StringData{sv.data(), sv.size()}); break; } case value::TypeTags::Array: { @@ -481,11 +485,11 @@ void appendValueToBsonObj(ObjBuilder& builder, } template void appendValueToBsonObj(BSONObjBuilder& builder, - StringData name, + std::string_view name, value::TypeTags tag, value::Value val); template void appendValueToBsonObj(UniqueBSONObjBuilder& builder, - StringData name, + std::string_view name, value::TypeTags tag, value::Value val); } // namespace bson diff --git a/src/mongo/db/exec/sbe/values/bson.h b/src/mongo/db/exec/sbe/values/bson.h index af37f80f76b..a8839d511fa 100644 --- a/src/mongo/db/exec/sbe/values/bson.h +++ b/src/mongo/db/exec/sbe/values/bson.h @@ -42,7 +42,7 @@ std::pair convertFrom(bool view, const char* advance(const char* be, size_t fieldNameSize); inline auto fieldNameView(const char* be) noexcept { - return StringData{be + 1}; + return std::string_view{be + 1}; } template @@ -53,7 +53,7 @@ void convertToBsonObj(ObjBuilder& builder, value::Object* obj); template void appendValueToBsonObj(ObjBuilder& builder, - StringData name, + std::string_view name, value::TypeTags tag, value::Value val); } // namespace bson diff --git a/src/mongo/db/exec/sbe/values/slot.h b/src/mongo/db/exec/sbe/values/slot.h index 44fcde13d1d..fbfc7239d3b 100644 --- a/src/mongo/db/exec/sbe/values/slot.h +++ b/src/mongo/db/exec/sbe/values/slot.h @@ -633,7 +633,7 @@ void readKeyStringValueIntoAccessors( template using SlotMap = absl::flat_hash_map; using SlotAccessorMap = SlotMap; -using FieldAccessorMap = StringMap>; +using FieldAccessorMap = absl::flat_hash_map>; using SlotSet = absl::flat_hash_set; using SlotVector = std::vector; diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp index 9fd512ea9d0..3522679d78f 100644 --- a/src/mongo/db/exec/sbe/values/value.cpp +++ b/src/mongo/db/exec/sbe/values/value.cpp @@ -44,32 +44,21 @@ namespace mongo { namespace sbe { namespace value { -namespace { -template -auto abslHash(const T& val) { - if constexpr (std::is_same_v) { - return absl::Hash{}(absl::string_view{val.rawData(), val.size()}); - } else { - return absl::Hash{}(val); - } -} -} // namespace - std::pair makeCopyBsonRegex(const BsonRegex& regex) { auto buffer = std::make_unique(regex.byteSize()); memcpy(buffer.get(), regex.data(), regex.byteSize()); return {TypeTags::bsonRegex, bitcastFrom(buffer.release())}; } -std::pair makeNewBsonRegex(StringData pattern, StringData flags) { +std::pair 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(totalSize); auto rawBuffer = buffer.get(); // Copy pattern first and flags after it. - memcpy(rawBuffer, pattern.rawData(), pattern.size()); - memcpy(rawBuffer + pattern.size() + 1, flags.rawData(), flags.size()); + 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'; @@ -77,7 +66,7 @@ std::pair makeNewBsonRegex(StringData pattern, StringData flags return {TypeTags::bsonRegex, bitcastFrom(buffer.release())}; } -std::pair makeCopyBsonJavascript(StringData code) { +std::pair makeCopyBsonJavascript(std::string_view code) { auto [_, strVal] = makeBigString(code); return {TypeTags::bsonJavascript, strVal}; } @@ -87,7 +76,7 @@ std::pair makeCopyKeyString(const KeyString::Value& inKey) { return {TypeTags::ksValue, bitcastFrom(k)}; } -std::pair makeNewPcreRegex(StringData pattern, StringData options) { +std::pair makeNewPcreRegex(std::string_view pattern, std::string_view options) { auto regex = std::make_unique(pattern, options); return {TypeTags::pcreRegex, bitcastFrom(regex.release())}; } @@ -105,11 +94,11 @@ void PcreRegex::_compile() { uassert(5073402, str::stream() << "Invalid Regex: " << compile_error, _pcrePtr != nullptr); } -int PcreRegex::execute(StringData stringView, int startPos, std::vector& buf) { +int PcreRegex::execute(std::string_view stringView, int startPos, std::vector& buf) { return pcre_exec(_pcrePtr, nullptr, - stringView.rawData(), - stringView.size(), + stringView.data(), + stringView.length(), startPos, 0, &(buf.front()), @@ -428,11 +417,11 @@ void writeValueToStream(T& stream, TypeTags tag, Value val) { case TypeTags::StringBig: case TypeTags::bsonString: { auto sv = getStringView(tag, val); - if (sv.size() <= kStringMaxDisplayLength) { - stream << '"' << sv << '"'; + if (sv.length() <= kStringMaxDisplayLength) { + stream << '"' << StringData{sv.data(), sv.size()} << '"'; } else { auto sub = sv.substr(0, kStringMaxDisplayLength); - stream << '"' << sub << '"' << "..."; + stream << '"' << StringData{sub.data(), sub.size()} << '"' << "..."; } break; } @@ -606,35 +595,36 @@ BSONType tagToType(TypeTags tag) noexcept { std::size_t hashValue(TypeTags tag, Value val, const CollatorInterface* collator) noexcept { switch (tag) { case TypeTags::NumberInt32: - return abslHash(bitcastTo(val)); + return absl::Hash{}(bitcastTo(val)); case TypeTags::RecordId: case TypeTags::NumberInt64: - return abslHash(bitcastTo(val)); + return absl::Hash{}(bitcastTo(val)); case TypeTags::NumberDouble: { // Force doubles to integers for hashing. auto dbl = bitcastTo(val); if (auto asInt = representAs(dbl); asInt) { - return abslHash(*asInt); + return absl::Hash{}(*asInt); } else { // Doubles not representable as int64_t will hash as doubles. - return abslHash(dbl); + return absl::Hash{}(dbl); } } case TypeTags::NumberDecimal: { // Force decimals to integers for hashing. auto dec = bitcastTo(val); if (auto asInt = representAs(dec); asInt) { - return abslHash(*asInt); + return absl::Hash{}(*asInt); } else if (auto asDbl = representAs(dec); asDbl) { - return abslHash(*asDbl); + return absl::Hash{}(*asDbl); } else { - return abslHash(dec.getValue().low64) ^ abslHash(dec.getValue().high64); + return absl::Hash{}(dec.getValue().low64) ^ + absl::Hash{}(dec.getValue().high64); } } case TypeTags::Date: - return abslHash(bitcastTo(val)); + return absl::Hash{}(bitcastTo(val)); case TypeTags::Timestamp: - return abslHash(bitcastTo(val)); + return absl::Hash{}(bitcastTo(val)); case TypeTags::Boolean: return bitcastTo(val); case TypeTags::Null: @@ -647,15 +637,18 @@ std::size_t hashValue(TypeTags tag, Value val, const CollatorInterface* collator case TypeTags::bsonString: { auto sv = getStringView(tag, val); if (collator) { - return abslHash(collator->getComparisonKey(sv).getKeyData()); + auto key = collator->getComparisonKey(StringData{sv.data(), sv.size()}); + auto keyData = key.getKeyData(); + return absl::Hash{}( + std::string_view{keyData.rawData(), keyData.size()}); } else { - return abslHash(sv); + return absl::Hash{}(sv); } } case TypeTags::ObjectId: { auto id = getObjectIdView(val); - return abslHash(readFromMemory(id->data())) ^ - abslHash(readFromMemory(id->data() + 8)); + return absl::Hash{}(readFromMemory(id->data())) ^ + absl::Hash{}(readFromMemory(id->data() + 8)); } case TypeTags::ksValue: { return getKeyStringView(val)->hash(); @@ -697,19 +690,19 @@ std::size_t hashValue(TypeTags tag, Value val, const CollatorInterface* collator memcpy(buffer, getRawPointerView(val), size); // Hash as if it is 64bit integer. - return abslHash(readFromMemory(buffer)); + return absl::Hash{}(readFromMemory(buffer)); } else { // Hash only the first 8 bytes. It should be enough. - return abslHash( + return absl::Hash{}( readFromMemory(getRawPointerView(val) + sizeof(uint32_t))); } } case TypeTags::bsonRegex: { auto regex = getBsonRegexView(val); - return abslHash(regex.dataView()); + return absl::Hash{}(regex.dataView()); } case TypeTags::bsonJavascript: - return abslHash(getBsonJavascriptView(val)); + return absl::Hash{}(getBsonJavascriptView(val)); default: break; } @@ -722,7 +715,7 @@ std::size_t hashValue(TypeTags tag, Value val, const CollatorInterface* collator * guarantees that the result will be exactlty -1, 0, or 1, which is important, because not all * comparison functions make that guarantee. * - * The StringData::compare(basic_string_view s) function, for example, only promises that it + * The std::string_view::compare(basic_string_view s) function, for example, only promises that it * will return a value less than 0 in the case that 'this' is less than 's,' whereas we want to * return exactly -1. */ @@ -768,7 +761,9 @@ std::pair compareValue(TypeTags lhsTag, auto lhsStr = getStringView(lhsTag, lhsValue); auto rhsStr = getStringView(rhsTag, rhsValue); - auto result = comparator ? comparator->compare(lhsStr, rhsStr) : lhsStr.compare(rhsStr); + auto result = comparator ? comparator->compare(StringData{lhsStr.data(), lhsStr.size()}, + StringData{rhsStr.data(), rhsStr.size()}) + : lhsStr.compare(rhsStr); return {TypeTags::NumberInt32, bitcastFrom(compareHelper(result, 0))}; } else if (lhsTag == TypeTags::Date && rhsTag == TypeTags::Date) { @@ -974,19 +969,19 @@ bool ObjectEnumerator::advance() { } } -StringData ObjectEnumerator::getFieldName() const { +std::string_view ObjectEnumerator::getFieldName() const { using namespace std::literals; if (_object) { if (_index < _object->size()) { return _object->field(_index); } else { - return ""_sd; + return ""sv; } } else { if (*_objectCurrent != 0) { return bson::fieldNameView(_objectCurrent); } else { - return ""_sd; + return ""sv; } } } diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h index a70a48bbbee..31ade47676d 100644 --- a/src/mongo/db/exec/sbe/values/value.h +++ b/src/mongo/db/exec/sbe/values/value.h @@ -422,7 +422,7 @@ public: } } - void push_back(StringData name, TypeTags tag, Value val) { + void push_back(std::string_view name, TypeTags tag, Value val) { if (tag != TypeTags::Nothing) { ValueGuard guard{tag, val}; // Reserve space in all vectors, they are the same size. We arbitrarily picked _typeTags @@ -437,7 +437,7 @@ public: } } - std::pair getField(StringData field) { + std::pair getField(std::string_view field) { for (size_t idx = 0; idx < _typeTags.size(); ++idx) { if (_names[idx] == field) { return {_typeTags[idx], _values[idx]}; @@ -597,11 +597,12 @@ private: */ class PcreRegex { public: - PcreRegex(StringData pattern, StringData options) : _pattern(pattern), _options(options) { + PcreRegex(std::string_view pattern, std::string_view options) + : _pattern(pattern), _options(options) { _compile(); } - PcreRegex(StringData pattern) : PcreRegex(pattern, "") {} + PcreRegex(std::string_view pattern) : PcreRegex(pattern, "") {} PcreRegex(const PcreRegex& other) : PcreRegex(other._pattern, other._options) {} @@ -638,7 +639,7 @@ public: * = 0 there was a match, but not enough space in the buffer * > 0 the number of matches */ - int execute(StringData input, int startPos, std::vector& buf); + int execute(std::string_view input, int startPos, std::vector& buf); size_t getNumberCaptures() const; @@ -714,7 +715,7 @@ inline size_t getStringLength(TypeTags tag, const Value& val) noexcept { /** * getStringView() should be preferred over getRawStringView() where possible. */ -inline StringData getStringView(TypeTags tag, const Value& val) noexcept { +inline std::string_view getStringView(TypeTags tag, const Value& val) noexcept { return {getRawStringView(tag, val), getStringLength(tag, val)}; } @@ -775,9 +776,9 @@ inline uint8_t* getBSONBinDataCompat(TypeTags tag, Value val) { } } -inline bool canUseSmallString(StringData input) { +inline bool canUseSmallString(std::string_view input) { auto length = input.size(); - auto ptr = input.rawData(); + auto ptr = input.data(); auto end = ptr + length; return length <= kSmallStringMaxLength && std::find(ptr, end, '\0') == end; } @@ -786,18 +787,18 @@ inline bool canUseSmallString(StringData input) { * Callers must check that canUseSmallString() returns true before calling this function. * makeNewString() should be preferred over makeSmallString() where possible. */ -inline std::pair makeSmallString(StringData input) { +inline std::pair makeSmallString(std::string_view input) { dassert(canUseSmallString(input)); Value smallString{0}; auto buf = getRawStringView(TypeTags::StringSmall, smallString); - memcpy(buf, input.rawData(), input.size()); + memcpy(buf, input.data(), input.size()); return {TypeTags::StringSmall, smallString}; } -inline std::pair makeBigString(StringData input) { +inline std::pair makeBigString(std::string_view input) { auto len = input.size(); - auto ptr = input.rawData(); + auto ptr = input.data(); invariant(len < static_cast(std::numeric_limits::max())); @@ -809,7 +810,7 @@ inline std::pair makeBigString(StringData input) { return {TypeTags::StringBig, reinterpret_cast(buf)}; } -inline std::pair makeNewString(StringData input) { +inline std::pair makeNewString(std::string_view input) { if (canUseSmallString(input)) { return makeSmallString(input); } else { @@ -885,7 +886,7 @@ inline KeyString::Value* getKeyStringView(Value val) noexcept { return reinterpret_cast(val); } -std::pair makeNewPcreRegex(StringData pattern, StringData options); +std::pair makeNewPcreRegex(std::string_view pattern, std::string_view options); std::pair makeCopyPcreRegex(const PcreRegex& regex); @@ -922,13 +923,13 @@ struct BsonRegex { BsonRegex(const char* rawValue) { pattern = rawValue; // We add 1 to account NULL byte after pattern. - flags = pattern.rawData() + pattern.size() + 1; + flags = pattern.data() + pattern.size() + 1; } - BsonRegex(StringData pattern, StringData flags) : pattern(pattern), flags(flags) { + BsonRegex(std::string_view pattern, std::string_view flags) : pattern(pattern), flags(flags) { // Ensure that flags follow right after pattern in memory. Otherwise 'dataView()' may return - // invalid 'StringData' object. - invariant(pattern.rawData() + pattern.size() + 1 == flags.rawData()); + // invalid 'std::string_view' object. + invariant(pattern.data() + pattern.size() + 1 == flags.data()); } size_t byteSize() const { @@ -937,15 +938,15 @@ struct BsonRegex { } const char* data() const { - return pattern.rawData(); + return pattern.data(); } - StringData dataView() const { + std::string_view dataView() const { return {data(), byteSize()}; } - StringData pattern; - StringData flags; + std::string_view pattern; + std::string_view flags; }; inline BsonRegex getBsonRegexView(Value val) noexcept { @@ -954,13 +955,13 @@ inline BsonRegex getBsonRegexView(Value val) noexcept { std::pair makeCopyBsonRegex(const BsonRegex& regex); -std::pair makeNewBsonRegex(StringData pattern, StringData flags); +std::pair makeNewBsonRegex(std::string_view pattern, std::string_view flags); -inline StringData getBsonJavascriptView(Value val) noexcept { +inline std::string_view getBsonJavascriptView(Value val) noexcept { return getStringView(TypeTags::StringBig, val); } -std::pair makeCopyBsonJavascript(StringData code); +std::pair makeCopyBsonJavascript(std::string_view code); std::pair makeCopyKeyString(const KeyString::Value& inKey); @@ -1145,7 +1146,7 @@ public: } } std::pair getViewOfValue() const; - StringData getFieldName() const; + std::string_view getFieldName() const; bool atEnd() const { if (_object) { diff --git a/src/mongo/db/exec/sbe/values/value_serialize_for_sorter_test.cpp b/src/mongo/db/exec/sbe/values/value_serialize_for_sorter_test.cpp index 3eedbc5dfbb..766bdac983a 100644 --- a/src/mongo/db/exec/sbe/values/value_serialize_for_sorter_test.cpp +++ b/src/mongo/db/exec/sbe/values/value_serialize_for_sorter_test.cpp @@ -58,16 +58,16 @@ TEST(ValueSerializeForSorter, Serialize) { testData->push_back(value::TypeTags::MaxKey, 0); testData->push_back(value::TypeTags::bsonUndefined, 0); - StringData smallString = "perfect"; + std::string_view smallString = "perfect"; invariant(sbe::value::canUseSmallString(smallString)); - StringData bigString = "too big string to fit into value"; + std::string_view bigString = "too big string to fit into value"; invariant(!sbe::value::canUseSmallString(bigString)); - StringData smallStringWithNull = "a\0b"; + std::string_view smallStringWithNull = "a\0b"; invariant(smallStringWithNull.size() <= sbe::value::kSmallStringMaxLength); - StringData bigStringWithNull = "too big string \0 to fit into value"; + std::string_view bigStringWithNull = "too big string \0 to fit into value"; invariant(bigStringWithNull.size() > sbe::value::kSmallStringMaxLength); - std::vector stringCases = { + std::vector stringCases = { smallString, smallStringWithNull, bigString, diff --git a/src/mongo/db/exec/sbe/vm/datetime.cpp b/src/mongo/db/exec/sbe/vm/datetime.cpp index 84839a4a2d4..09c4188ea17 100644 --- a/src/mongo/db/exec/sbe/vm/datetime.cpp +++ b/src/mongo/db/exec/sbe/vm/datetime.cpp @@ -45,7 +45,9 @@ bool isValidTimezone(value::TypeTags timezoneTag, return false; } auto timezoneStringView = value::getStringView(timezoneTag, timezoneValue); - return timezoneStringView.empty() || timezoneDB->isTimeZoneIdentifier(timezoneStringView); + return timezoneStringView.empty() || + timezoneDB->isTimeZoneIdentifier( + StringData{timezoneStringView.data(), timezoneStringView.size()}); } TimeZone getTimezone(value::TypeTags timezoneTag, @@ -55,7 +57,7 @@ TimeZone getTimezone(value::TypeTags timezoneTag, if (timezoneStr.empty()) { return timezoneDB->utcZone(); } else { - return timezoneDB->getTimeZone(timezoneStr); + return timezoneDB->getTimeZone(StringData{timezoneStr.data(), timezoneStr.size()}); } } diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp index 09361aaea04..dd207101ee6 100644 --- a/src/mongo/db/exec/sbe/vm/vm.cpp +++ b/src/mongo/db/exec/sbe/vm/vm.cpp @@ -750,9 +750,12 @@ std::tuple ByteCode::aggLast(value::TypeTag } -bool hasSeparatorAt(size_t idx, StringData input, StringData separator) { - return (idx + separator.size() <= input.size()) && - input.substr(idx, separator.size()) == separator; +bool hasSeparatorAt(size_t idx, std::string_view input, std::string_view separator) { + if (separator.size() + idx > input.size()) { + return false; + } + + return input.compare(idx, separator.size(), separator) == 0; } std::tuple ByteCode::builtinSplit(ArityType arity) { @@ -772,7 +775,7 @@ std::tuple ByteCode::builtinSplit(ArityType size_t splitStart = 0; size_t splitPos; - while ((splitPos = input.find(separator, splitStart)) != std::string::npos) { + while ((splitPos = input.find(separator, splitStart)) != std::string_view::npos) { auto [tag, val] = value::makeNewString(input.substr(splitStart, splitPos - splitStart)); arr->push_back(tag, val); @@ -832,7 +835,7 @@ std::tuple ByteCode::builtinDropFields(Arit } else if (tagInObj == value::TypeTags::Object) { auto objRoot = value::getObjectView(valInObj); for (size_t idx = 0; idx < objRoot->size(); ++idx) { - StringData sv(objRoot->field(idx)); + std::string_view sv(objRoot->field(idx)); if (restrictFieldsSet.count(sv) == 0) { @@ -944,7 +947,7 @@ std::tuple ByteCode::builtinNewKeyString(Ar kb.appendNumberLong(num); } else if (value::isString(tag)) { auto str = value::getStringView(tag, val); - kb.appendString(str); + kb.appendString(StringData{str.data(), str.length()}); } else { uasserted(4822802, "unsuppored key string type"); } @@ -1151,16 +1154,20 @@ std::tuple ByteCode::builtinReplaceOne(Arit return {false, value::TypeTags::Nothing, 0}; } - auto input = value::getStringView(typeTagInputStr, valueInputStr); - auto find = value::getStringView(typeTagFindStr, valueFindStr); - auto replacement = value::getStringView(typeTagReplacementStr, valueReplacementStr); + auto inputStrView = value::getStringView(typeTagInputStr, valueInputStr); + auto findStrView = value::getStringView(typeTagFindStr, valueFindStr); + auto replacementStrView = value::getStringView(typeTagReplacementStr, valueReplacementStr); // If find string is empty, return nothing, since an empty find will match every position in a // string. - if (find.empty()) { + if (findStrView.empty()) { return {false, value::TypeTags::Nothing, 0}; } + auto input = StringData(inputStrView.data(), inputStrView.length()); + auto find = StringData(findStrView.data(), findStrView.length()); + auto replacement = StringData(replacementStrView.data(), replacementStrView.length()); + // If find string is not found, return the original string. size_t startIndex = input.find(find); if (startIndex == std::string::npos) { @@ -1175,7 +1182,8 @@ std::tuple ByteCode::builtinReplaceOne(Arit output << input.substr(endIndex); auto strData = output.stringData(); - auto [outputStrTypeTag, outputStrValue] = sbe::value::makeNewString(strData); + auto [outputStrTypeTag, outputStrValue] = + sbe::value::makeNewString({strData.rawData(), strData.size()}); return {true, outputStrTypeTag, outputStrValue}; } @@ -1313,7 +1321,9 @@ std::tuple builtinDateHelper( invariant(timeZoneDB); auto tzString = value::getStringView(typeTagTz, valueTz); - const auto tz = tzString == "" ? timeZoneDB->utcZone() : timeZoneDB->getTimeZone(tzString); + const auto tz = tzString == "" + ? timeZoneDB->utcZone() + : timeZoneDB->getTimeZone(StringData{tzString.data(), tzString.size()}); auto date = computeDateFn(tz, @@ -1848,7 +1858,8 @@ std::tuple ByteCode::builtinConcat(ArityTyp if (!value::isString(tag)) { return {false, value::TypeTags::Nothing, 0}; } - result << sbe::value::getStringView(tag, value); + auto sv = sbe::value::getStringView(tag, value); + result << StringData{sv.data(), sv.size()}; } auto [strTag, strValue] = sbe::value::makeNewString(result.str()); @@ -1945,7 +1956,7 @@ std::tuple ByteCode::builtinIndexOfBytes(Ar return {false, value::TypeTags::Nothing, 0}; } // Check for valid bounds. - if (static_cast(startIndex) > str.size()) { + if (static_cast(startIndex) > str.length()) { return {false, value::TypeTags::NumberInt32, value::bitcastFrom(-1)}; } } @@ -1992,7 +2003,7 @@ std::tuple ByteCode::builtinIndexOfCP(Arity return {false, value::TypeTags::Nothing, 0}; } // Check for valid bounds. - if (static_cast(startCodePointIndex) > str.size()) { + if (static_cast(startCodePointIndex) > str.length()) { return {false, value::TypeTags::NumberInt32, value::bitcastFrom(-1)}; } } @@ -2033,7 +2044,7 @@ std::tuple ByteCode::builtinIndexOfCP(Arity byteIndex = startByteIndex; for (codePointIndex = startCodePointIndex; codePointIndex < endCodePointIndex; ++codePointIndex) { - if (str.substr(byteIndex, substr.size()).compare(substr) == 0) { + if (str.compare(byteIndex, substr.size(), substr) == 0) { return { false, value::TypeTags::NumberInt32, value::bitcastFrom(codePointIndex)}; } @@ -2077,7 +2088,7 @@ std::tuple ByteCode::builtinIsTimezone(Arit return {false, value::TypeTags::Boolean, false}; } auto timezoneStr = value::getStringView(timezoneTag, timezoneVal); - if (timezoneDB->isTimeZoneIdentifier(timezoneStr)) { + if (timezoneDB->isTimeZoneIdentifier((StringData{timezoneStr.data(), timezoneStr.size()}))) { return {false, value::TypeTags::Boolean, true}; } return {false, value::TypeTags::Boolean, false}; @@ -2311,7 +2322,7 @@ namespace { * ...} from the result of pcre_exec(). */ std::tuple buildRegexMatchResultObject( - StringData inputString, + std::string_view inputString, const std::vector& capturesBuffer, size_t numCaptures, uint32_t& startBytePos, @@ -2408,7 +2419,7 @@ std::tuple buildRegexMatchResultObject( * returned is true/false. */ std::tuple pcreNextMatch(value::PcreRegex* pcre, - StringData inputString, + std::string_view inputString, std::vector& capturesBuffer, uint32_t& startBytePos, uint32_t& codePointPos, @@ -2443,7 +2454,7 @@ std::tuple pcreNextMatch(value::PcreRegex* */ std::tuple pcreFirstMatch( value::PcreRegex* pcre, - StringData inputString, + std::string_view inputString, bool isMatch = false, std::vector* capturesBuffer = nullptr, uint32_t* startBytePos = nullptr, @@ -2496,15 +2507,16 @@ std::pair collComparisonKey(value::TypeTags tag, // For strings, call CollatorInterface::getComparisonKey() to obtain the comparison key. if (value::isString(tag)) { - auto compKey = collator->getComparisonKey(value::getStringView(tag, val)); + auto sv = value::getStringView(tag, val); + auto compKey = collator->getComparisonKey(StringData{sv.data(), sv.size()}); auto keyData = compKey.getKeyData(); - return value::makeNewString(keyData); + return value::makeNewString(std::string_view{keyData.rawData(), keyData.size()}); } // For collatable types other than strings (such as arrays and objects), we take the slow // path and round-trip the value through BSON. BSONObjBuilder input; - bson::appendValueToBsonObj(input, ""_sd, tag, val); + bson::appendValueToBsonObj(input, ""sv, tag, val); BSONObjBuilder output; CollationIndexKey::collationAwareIndexKeyAppend(input.obj().firstElement(), collator, &output); @@ -2613,8 +2625,8 @@ std::tuple ByteCode::builtinRegexFindAll(Ar startBytePos += str::getCodePointLength(inputString[startBytePos]); ++codePointPos; } else { - startBytePos += matchString.size(); - for (size_t byteIdx = 0; byteIdx < matchString.size(); ++codePointPos) { + startBytePos += matchString.length(); + for (size_t byteIdx = 0; byteIdx < matchString.length(); ++codePointPos) { byteIdx += str::getCodePointLength(matchString[byteIdx]); } } @@ -2789,7 +2801,7 @@ std::tuple ByteCode::builtinHasNullBytes(Ar } auto stringView = value::getStringView(strType, strValue); - auto hasNullBytes = stringView.find('\0') != std::string::npos; + auto hasNullBytes = stringView.find('\0') != std::string_view::npos; return {false, value::TypeTags::Boolean, value::bitcastFrom(hasNullBytes)}; } diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h index 1d11e835858..b98f3261d12 100644 --- a/src/mongo/db/exec/sbe/vm/vm.h +++ b/src/mongo/db/exec/sbe/vm/vm.h @@ -79,8 +79,10 @@ std::pair genericCompare( auto lhsStr = getStringView(lhsTag, lhsValue); auto rhsStr = getStringView(rhsTag, rhsValue); - auto result = - op(comparator ? comparator->compare(lhsStr, rhsStr) : lhsStr.compare(rhsStr), 0); + auto result = op(comparator ? comparator->compare(StringData{lhsStr.data(), lhsStr.size()}, + StringData{rhsStr.data(), rhsStr.size()}) + : lhsStr.compare(rhsStr), + 0); return {value::TypeTags::Boolean, value::bitcastFrom(result)}; } else if (lhsTag == value::TypeTags::Date && rhsTag == value::TypeTags::Date) { diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index f008c6e7b4c..0db59301a5c 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -1972,8 +1972,12 @@ TimeUnit ExpressionDateDiff::convertToTimeUnit(const Value& value) { str::stream() << "$dateDiff requires 'unit' to be a string, but got " << typeName(value.getType()), BSONType::String == value.getType()); - return addContextToAssertionException([&] { return parseTimeUnit(value.getStringData()); }, - "$dateDiff parameter 'unit' value parsing failed"_sd); + auto valueAsString = value.getStringData(); + return addContextToAssertionException( + [&]() { + return parseTimeUnit(std::string_view{valueAsString.rawData(), valueAsString.size()}); + }, + "$dateDiff parameter 'unit' value parsing failed"_sd); } DayOfWeek ExpressionDateDiff::parseStartOfWeek(const Value& value) { @@ -1981,8 +1985,11 @@ DayOfWeek ExpressionDateDiff::parseStartOfWeek(const Value& value) { str::stream() << "$dateDiff requires 'startOfWeek' to be a string, but got " << typeName(value.getType()), BSONType::String == value.getType()); + auto valueAsString = value.getStringData(); return addContextToAssertionException( - [&] { return parseDayOfWeek(value.getStringData()); }, + [&]() { + return parseDayOfWeek(std::string_view{valueAsString.rawData(), valueAsString.size()}); + }, "$dateDiff parameter 'startOfWeek' value parsing failed"_sd); } diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp index dbbb9093759..6b99a116b3d 100644 --- a/src/mongo/db/query/sbe_stage_builder.cpp +++ b/src/mongo/db/query/sbe_stage_builder.cpp @@ -454,10 +454,11 @@ std::pair, PlanStageSlots> SlotBasedStageBuilder for (auto&& field : vsn->indexKeyPattern) { if (reqs.getIndexKeyBitset()->test(indexKeyPos)) { indexKeySlots.push_back(_slotIdGenerator.generate()); - projections.emplace(indexKeySlots.back(), - makeFunction("getField"_sd, - sbe::makeE(resultSlot), - makeConstant(field.fieldName()))); + projections.emplace( + indexKeySlots.back(), + makeFunction("getField"sv, + sbe::makeE(resultSlot), + makeConstant(std::string_view{field.fieldName()}))); } ++indexKeyPos; } @@ -514,7 +515,10 @@ std::pair, PlanStageSlots> SlotBasedStageBuilder size_t i = 0; for (auto&& elem : ixn->index.keyPattern) { - mkObjArgs.emplace_back(sbe::makeE(elem.fieldNameStringData())); + auto fieldName = elem.fieldNameStringData(); + + mkObjArgs.emplace_back(sbe::makeE( + std::string_view{fieldName.rawData(), fieldName.size()})); mkObjArgs.emplace_back(sbe::makeE((*outputs.getIndexKeySlots())[i++])); } @@ -714,19 +718,20 @@ std::pair, PlanStageSlots> SlotBasedStageBuilder // Generate projection to get the value of the sort key. Ideally, this should be // tracked by a 'reference tracker' at higher level. auto fieldName = part.fieldPath->getFieldName(0); + auto fieldNameSV = std::string_view{fieldName.rawData(), fieldName.size()}; - auto getSortFieldExpr = makeFunction("getField"_sd, + auto getSortFieldExpr = makeFunction("getField"sv, sbe::makeE(outputs.get(kResult)), - sbe::makeE(fieldName)); + sbe::makeE(fieldNameSV)); if (auto collatorSlot = _data.env->getSlotIfExists("collator"_sd); collatorSlot) { - getSortFieldExpr = makeFunction("collComparisonKey"_sd, + getSortFieldExpr = makeFunction("collComparisonKey"sv, std::move(getSortFieldExpr), sbe::makeE(*collatorSlot)); } // According to MQL semantics, missing values are treated as nulls during sorting. - getSortFieldExpr = makeFunction("fillEmpty"_sd, + getSortFieldExpr = makeFunction("fillEmpty"sv, std::move(getSortFieldExpr), makeConstant(sbe::value::TypeTags::Null, 0)); @@ -1362,7 +1367,7 @@ SlotBasedStageBuilder::makeUnionForTailableCollScan(const QuerySolutionNode* roo auto&& [anchorBranchSlots, anchorBranch] = makeUnionBranch(false); anchorBranch = sbe::makeS>( std::move(anchorBranch), - makeNot(makeFunction("exists"_sd, sbe::makeE(resumeRecordIdSlot))), + makeNot(makeFunction("exists"sv, sbe::makeE(resumeRecordIdSlot))), root->nodeId()); // Build a resume branch of the union and add a constant filter on op of it, so that it would @@ -1370,7 +1375,7 @@ SlotBasedStageBuilder::makeUnionForTailableCollScan(const QuerySolutionNode* roo auto&& [resumeBranchSlots, resumeBranch] = makeUnionBranch(true); resumeBranch = sbe::makeS>( sbe::makeS(std::move(resumeBranch), boost::none, 1, root->nodeId()), - sbe::makeE("exists"_sd, + sbe::makeE("exists"sv, sbe::makeEs(sbe::makeE(resumeRecordIdSlot))), root->nodeId()); diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp index 45ef557b5a5..4b0de4bdbfd 100644 --- a/src/mongo/db/query/sbe_stage_builder_expression.cpp +++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp @@ -182,12 +182,15 @@ std::pair generateTraverseHelper( // Generate the projection stage to read a sub-field at the current nested level and bind it // to 'fieldSlot'. - inputStage = makeProject(std::move(inputStage), - planNodeId, - fieldSlot, - makeFunction("getField"_sd, - sbe::makeE(inputSlot), - sbe::makeE(fp.getFieldName(level)))); + inputStage = makeProject( + std::move(inputStage), + planNodeId, + fieldSlot, + makeFunction( + "getField"sv, sbe::makeE(inputSlot), sbe::makeE([&]() { + auto fieldName = fp.getFieldName(level); + return std::string_view{fieldName.rawData(), fieldName.size()}; + }()))); EvalStage innerBranch; if (level == fp.getPathLength() - 1) { @@ -1225,7 +1228,7 @@ public: // Get child expressions. auto startOfWeekExpression = expr->isStartOfWeekSpecified() ? _context->popExpr() : nullptr; auto timezoneExpression = - expr->isTimezoneSpecified() ? _context->popExpr() : makeConstant("UTC"_sd); + expr->isTimezoneSpecified() ? _context->popExpr() : makeConstant("UTC"sv); auto unitExpression = _context->popExpr(); auto endDateExpression = _context->popExpr(); auto startDateExpression = _context->popExpr(); @@ -1244,7 +1247,7 @@ public: // "dateDiff" built-in function does not accept non-string type values for this // parameter. arguments.push_back(sbe::makeE( - unitIsWeekRef.clone(), startOfWeekRef.clone(), makeConstant("sun"_sd))); + unitIsWeekRef.clone(), startOfWeekRef.clone(), makeConstant("sun"sv))); } // Set bindings for the frame. @@ -1254,11 +1257,11 @@ public: bindings.push_back(std::move(timezoneExpression)); if (expr->isStartOfWeekSpecified()) { bindings.push_back(std::move(startOfWeekExpression)); - bindings.push_back(generateIsEqualToStringCheck(unitRef, "week"_sd)); + bindings.push_back(generateIsEqualToStringCheck(unitRef, "week"sv)); } // Create an expression to invoke built-in "dateDiff" function. - auto dateDiffFunctionCall = sbe::makeE("dateDiff"_sd, std::move(arguments)); + auto dateDiffFunctionCall = sbe::makeE("dateDiff"sv, std::move(arguments)); // Create expressions to check that each argument to "dateDiff" function exists, is not // null, and is of the correct type. @@ -2850,7 +2853,7 @@ private: * Creates a boolean expression to check if 'variable' is equal to string 'string'. */ static std::unique_ptr generateIsEqualToStringCheck( - const sbe::EVariable& variable, StringData string) { + const sbe::EVariable& variable, std::string_view string) { return sbe::makeE(sbe::EPrimBinary::logicAnd, makeFunction("isString", variable.clone()), sbe::makeE(sbe::EPrimBinary::eq, @@ -3075,15 +3078,14 @@ private: switch (setOp) { case SetOperation::Difference: return std::make_pair("setDifference"_sd, - collatorSlot ? "collSetDifference"_sd - : "setDifference"_sd); + collatorSlot ? "collSetDifference"sv : "setDifference"sv); case SetOperation::Intersection: return std::make_pair("setIntersection"_sd, - collatorSlot ? "collSetIntersection"_sd - : "setIntersection"_sd); + collatorSlot ? "collSetIntersection"sv + : "setIntersection"sv); case SetOperation::Union: return std::make_pair("setUnion"_sd, - collatorSlot ? "collSetUnion"_sd : "setUnion"_sd); + collatorSlot ? "collSetUnion"sv : "setUnion"sv); default: MONGO_UNREACHABLE; } diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp index 562b059dbb3..044b8ae2696 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.cpp +++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp @@ -332,13 +332,13 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage, // Generate the projection stage to read a sub-field at the current nested level and bind it // to 'fieldSlot'. - auto fieldName = fp.getPart(level); + std::string_view fieldName{fp.getPart(level).rawData(), fp.getPart(level).size()}; auto fieldSlot{slotIdGenerator->generate()}; auto fromBranch = makeProject(std::move(inputStage), planNodeId, fieldSlot, - sbe::makeE("getField"_sd, + sbe::makeE("getField"sv, sbe::makeEs(sbe::makeE(inputSlot), sbe::makeE(fieldName)))); diff --git a/src/mongo/db/query/sbe_stage_builder_helpers.cpp b/src/mongo/db/query/sbe_stage_builder_helpers.cpp index 31f214a9521..86c5bad1eb2 100644 --- a/src/mongo/db/query/sbe_stage_builder_helpers.cpp +++ b/src/mongo/db/query/sbe_stage_builder_helpers.cpp @@ -197,7 +197,7 @@ std::unique_ptr makeLimitCoScanTree(PlanNodeId planNodeId, long std::unique_ptr makeFillEmptyFalse(std::unique_ptr e) { using namespace std::literals; - return makeFunction("fillEmpty"_sd, + return makeFunction("fillEmpty"sv, std::move(e), sbe::makeE(sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom(false))); @@ -212,13 +212,13 @@ std::unique_ptr makeVariable(sbe::value::SlotId slotId, std::unique_ptr makeFillEmptyNull(std::unique_ptr e) { using namespace std::literals; return makeFunction( - "fillEmpty"_sd, std::move(e), sbe::makeE(sbe::value::TypeTags::Null, 0)); + "fillEmpty"sv, std::move(e), sbe::makeE(sbe::value::TypeTags::Null, 0)); } std::unique_ptr makeNothingArrayCheck( std::unique_ptr isArrayInput, std::unique_ptr otherwise) { using namespace std::literals; - return sbe::makeE(makeFunction("isArray"_sd, std::move(isArrayInput)), + return sbe::makeE(makeFunction("isArray"sv, std::move(isArrayInput)), sbe::makeE(sbe::value::TypeTags::Nothing, 0), std::move(otherwise)); } @@ -228,11 +228,15 @@ std::unique_ptr generateShardKeyBinding( sbe::value::FrameIdGenerator& frameIdGenerator, std::unique_ptr inputExpr, int level) { + using namespace std::literals; invariant(level >= 0); auto makeGetFieldKeyPattern = [&](std::unique_ptr slot) { - return makeFillEmptyNull(makeFunction( - "getField"_sd, std::move(slot), sbe::makeE(keyPatternField[level]))); + return makeFillEmptyNull( + makeFunction("getField"sv, std::move(slot), sbe::makeE([&]() { + const auto fieldName = keyPatternField[level]; + return std::string_view{fieldName.rawData(), fieldName.size()}; + }()))); }; if (level == keyPatternField.numParts() - 1) { @@ -527,7 +531,7 @@ std::pair> generateVirtu projectSlots.emplace_back(slotIdGenerator->generate()); projections.emplace( projectSlots.back(), - makeFunction("getElement"_sd, + makeFunction("getElement"sv, sbe::makeE(scanSlot), sbe::makeE(sbe::value::TypeTags::NumberInt32, sbe::value::bitcastFrom(i)))); diff --git a/src/mongo/db/query/sbe_stage_builder_helpers.h b/src/mongo/db/query/sbe_stage_builder_helpers.h index 65b3371d034..d5956b0ca8d 100644 --- a/src/mongo/db/query/sbe_stage_builder_helpers.h +++ b/src/mongo/db/query/sbe_stage_builder_helpers.h @@ -188,7 +188,7 @@ std::unique_ptr makeFillEmptyFalse(std::unique_ptr -inline std::unique_ptr makeFunction(StringData name, Args&&... args) { +inline std::unique_ptr makeFunction(std::string_view name, Args&&... args) { return sbe::makeE(name, sbe::makeEs(std::forward(args)...)); } @@ -197,7 +197,7 @@ inline auto makeConstant(sbe::value::TypeTags tag, T value) { return sbe::makeE(tag, sbe::value::bitcastFrom(value)); } -inline auto makeConstant(StringData str) { +inline auto makeConstant(std::string_view str) { auto [tag, value] = sbe::value::makeNewString(str); return sbe::makeE(tag, value); } diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp index 84a20dfd9a4..1eee1a968f7 100644 --- a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp +++ b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp @@ -301,10 +301,10 @@ generateOptimizedMultiIntervalIndexScan( for (auto&& [lowKey, highKey] : intervals) { auto [tag, val] = sbe::value::makeNewObject(); auto obj = sbe::value::getObjectView(val); - obj->push_back("l"_sd, + obj->push_back("l"sv, sbe::value::TypeTags::ksValue, sbe::value::bitcastFrom(lowKey.release())); - obj->push_back("h"_sd, + obj->push_back("h"sv, sbe::value::TypeTags::ksValue, sbe::value::bitcastFrom(highKey.release())); arr->push_back(tag, val); @@ -334,13 +334,13 @@ generateOptimizedMultiIntervalIndexScan( std::move(unwind), planNodeId, lowKeySlot, - sbe::makeE("getField"_sd, - sbe::makeEs(sbe::makeE(unwindSlot), - sbe::makeE("l"_sd))), + sbe::makeE( + "getField"sv, + sbe::makeEs(sbe::makeE(unwindSlot), sbe::makeE("l"sv))), highKeySlot, - sbe::makeE("getField"_sd, + sbe::makeE("getField"sv, sbe::makeEs(sbe::makeE(unwindSlot), - sbe::makeE("h"_sd)))); + sbe::makeE("h"sv)))); auto ixscan = sbe::makeS(collection->uuid(), indexName, @@ -609,14 +609,14 @@ generateGenericMultiIntervalIndexScan(const CollectionPtr& collection, std::move(unionStage), spoolId, makeSlotVector(resultSlot, std::move(indexKeySlots)), - makeNot(makeFunction("isRecordId"_sd, sbe::makeE(resultSlot))), + makeNot(makeFunction("isRecordId"sv, sbe::makeE(resultSlot))), ixn->nodeId()); // Finally, add a filter stage on top to filter out seek keys and return only recordIds. return {resultSlot, sbe::makeS>( std::move(spool), - sbe::makeE("isRecordId"_sd, + sbe::makeE("isRecordId"sv, sbe::makeEs(sbe::makeE(resultSlot))), ixn->nodeId())}; } diff --git a/src/mongo/db/query/sbe_stage_builder_projection.cpp b/src/mongo/db/query/sbe_stage_builder_projection.cpp index 4bba27c9833..896b36fba27 100644 --- a/src/mongo/db/query/sbe_stage_builder_projection.cpp +++ b/src/mongo/db/query/sbe_stage_builder_projection.cpp @@ -463,7 +463,7 @@ public: childLevelStage = sbe::makeS>( std::move(mkBsonStage), - makeFunction("isObject"_sd, sbe::makeE(childLevelInputSlot)), + makeFunction("isObject"sv, sbe::makeE(childLevelInputSlot)), _context->planNodeId); } @@ -497,7 +497,7 @@ public: sbe::makeProjectStage(std::move(parentLevelStage), _context->planNodeId, childLevelInputSlot, - makeFunction("getField"_sd, + makeFunction("getField"sv, sbe::makeE(parentLevelInputSlot), makeConstant(_context->topFrontField()))); } @@ -603,8 +603,8 @@ public: auto isObjectOrArrayExpr = makeBinaryOp( sbe::EPrimBinary::logicOr, - makeFunction("isObject"_sd, sbe::makeE(inputArraySlot)), - makeFunction("isArray"_sd, sbe::makeE(inputArraySlot))); + makeFunction("isObject"sv, sbe::makeE(inputArraySlot)), + makeFunction("isArray"sv, sbe::makeE(inputArraySlot))); return sbe::makeS>(std::move(elemMatchPredicateTree), std::move(isObjectOrArrayExpr), _context->planNodeId); @@ -680,7 +680,7 @@ public: std::move(_context->topLevel().evalStage), _context->planNodeId, inputArraySlot, - makeFunction("getField"_sd, + makeFunction("getField"sv, inputDocumentVariable.clone(), sbe::makeE(_context->topFrontField()))); @@ -688,7 +688,7 @@ public: std::move(fromBranch), _context->planNodeId, traversingAnArrayFlagSlot, - makeFunction("isArray"_sd, sbe::makeE(inputArraySlot))); + makeFunction("isArray"sv, sbe::makeE(inputArraySlot))); auto filteredArraySlot = _context->slotIdGenerator->generate(); auto traverseStage = @@ -813,7 +813,7 @@ public: childLevelStage = sbe::makeS( std::move(childLevelStage), makeLimitCoScanTree(_context->planNodeId), - makeFunction("isObject"_sd, sbe::makeE(childLevelInputSlot)), + makeFunction("isObject"sv, sbe::makeE(childLevelInputSlot)), sbe::makeSV(childLevelObjSlot), sbe::makeSV(childLevelInputSlot), sbe::makeSV(childLevelResultSlot), @@ -831,7 +831,7 @@ public: sbe::makeProjectStage(std::move(parentLevelStage), _context->planNodeId, childLevelInputSlot, - makeFunction("getField"_sd, + makeFunction("getField"sv, sbe::makeE(parentLevelInputSlot), makeConstant(_context->topFrontField()))); } else { @@ -869,7 +869,7 @@ public: using namespace std::literals; auto arrayFromField = - makeFunction("getField"_sd, + makeFunction("getField"sv, sbe::makeE(_context->topLevel().inputSlot), makeConstant(_context->topFrontField())); auto binds = sbe::makeEs(std::move(arrayFromField)); @@ -884,7 +884,7 @@ public: } auto extractSubArrayExpr = sbe::makeE( - makeFunction("isArray"_sd, arrayVariable.clone()), + makeFunction("isArray"sv, arrayVariable.clone()), sbe::makeE("extractSubArray", std::move(arguments)), arrayVariable.clone()); -- cgit v1.2.1