summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Lapkov <nikita.lapkov@mongodb.com>2020-11-04 16:49:42 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-09 12:38:01 +0000
commita4c597067a26e71859ca07de33dacde98c1747f1 (patch)
tree744177b24f3693facdc5165e1c84a500b5420e67
parentb806ef292dad8608db70cefe97cc90a1603182ca (diff)
downloadmongo-a4c597067a26e71859ca07de33dacde98c1747f1.tar.gz
SERVER-50905: Add RecordId type in SBE
-rw-r--r--src/mongo/db/exec/sbe/expressions/expression.cpp2
-rw-r--r--src/mongo/db/exec/sbe/stages/ix_scan.cpp2
-rw-r--r--src/mongo/db/exec/sbe/stages/scan.cpp6
-rw-r--r--src/mongo/db/exec/sbe/values/bson.cpp2
-rw-r--r--src/mongo/db/exec/sbe/values/slot.cpp3
-rw-r--r--src/mongo/db/exec/sbe/values/value.cpp11
-rw-r--r--src/mongo/db/exec/sbe/values/value.h5
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.cpp19
-rw-r--r--src/mongo/db/exec/sbe/vm/vm.h2
-rw-r--r--src/mongo/db/query/plan_executor_sbe.cpp6
-rw-r--r--src/mongo/db/query/sbe_stage_builder_coll_scan.cpp4
-rw-r--r--src/mongo/db/query/sbe_stage_builder_index_scan.cpp4
12 files changed, 55 insertions, 11 deletions
diff --git a/src/mongo/db/exec/sbe/expressions/expression.cpp b/src/mongo/db/exec/sbe/expressions/expression.cpp
index 3eee0f6a57b..1fc6504b2b0 100644
--- a/src/mongo/db/exec/sbe/expressions/expression.cpp
+++ b/src/mongo/db/exec/sbe/expressions/expression.cpp
@@ -449,6 +449,8 @@ static stdx::unordered_map<std::string, InstrFn> kInstrFunctions = {
InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendIsBinData, false}},
{"isDate", InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendIsDate, false}},
{"isNaN", InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendIsNaN, false}},
+ {"isRecordId",
+ InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendIsRecordId, false}},
{"sum", InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendSum, true}},
{"min", InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendMin, true}},
{"max", InstrFn{[](size_t n) { return n == 1; }, &vm::CodeFragment::appendMax, true}},
diff --git a/src/mongo/db/exec/sbe/stages/ix_scan.cpp b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
index 78bf0b09de5..a45e25542d2 100644
--- a/src/mongo/db/exec/sbe/stages/ix_scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/ix_scan.cpp
@@ -274,7 +274,7 @@ PlanState IndexScanStage::getNext() {
}
if (_recordIdAccessor) {
- _recordIdAccessor->reset(value::TypeTags::NumberInt64,
+ _recordIdAccessor->reset(value::TypeTags::RecordId,
value::bitcastFrom<int64_t>(_nextRecord->loc.repr()));
}
diff --git a/src/mongo/db/exec/sbe/stages/scan.cpp b/src/mongo/db/exec/sbe/stages/scan.cpp
index 029cdcb9587..f4d428fa3ed 100644
--- a/src/mongo/db/exec/sbe/stages/scan.cpp
+++ b/src/mongo/db/exec/sbe/stages/scan.cpp
@@ -184,7 +184,7 @@ void ScanStage::open(bool reOpen) {
const auto msgTag = tag;
uassert(ErrorCodes::BadValue,
str::stream() << "seek key is wrong type: " << msgTag,
- tag == value::TypeTags::NumberInt64);
+ tag == value::TypeTags::RecordId);
_key = RecordId{value::bitcastTo<int64_t>(val)};
}
@@ -221,7 +221,7 @@ PlanState ScanStage::getNext() {
}
if (_recordIdAccessor) {
- _recordIdAccessor->reset(value::TypeTags::NumberInt64,
+ _recordIdAccessor->reset(value::TypeTags::RecordId,
value::bitcastFrom<int64_t>(nextRecord->id.repr()));
}
@@ -527,7 +527,7 @@ PlanState ParallelScanStage::getNext() {
}
if (_recordIdAccessor) {
- _recordIdAccessor->reset(value::TypeTags::NumberInt64,
+ _recordIdAccessor->reset(value::TypeTags::RecordId,
value::bitcastFrom<int64_t>(nextRecord->id.repr()));
}
diff --git a/src/mongo/db/exec/sbe/values/bson.cpp b/src/mongo/db/exec/sbe/values/bson.cpp
index 5f28c6122c0..a0f45a576bb 100644
--- a/src/mongo/db/exec/sbe/values/bson.cpp
+++ b/src/mongo/db/exec/sbe/values/bson.cpp
@@ -231,6 +231,7 @@ void convertToBsonObj(BSONArrayBuilder& builder, value::ArrayEnumerator arr) {
case value::TypeTags::NumberInt32:
builder.append(value::bitcastTo<int32_t>(val));
break;
+ case value::TypeTags::RecordId:
case value::TypeTags::NumberInt64:
builder.append(value::bitcastTo<int64_t>(val));
break;
@@ -317,6 +318,7 @@ void convertToBsonObj(BSONObjBuilder& builder, value::Object* obj) {
case value::TypeTags::NumberInt32:
builder.append(name, value::bitcastTo<int32_t>(val));
break;
+ case value::TypeTags::RecordId:
case value::TypeTags::NumberInt64:
builder.append(name, value::bitcastTo<int64_t>(val));
break;
diff --git a/src/mongo/db/exec/sbe/values/slot.cpp b/src/mongo/db/exec/sbe/values/slot.cpp
index 65017593bd1..401718fe24d 100644
--- a/src/mongo/db/exec/sbe/values/slot.cpp
+++ b/src/mongo/db/exec/sbe/values/slot.cpp
@@ -46,6 +46,7 @@ static std::pair<TypeTags, Value> deserializeTagVal(BufReader& buf) {
case TypeTags::NumberInt32:
val = bitcastFrom<int32_t>(buf.read<int32_t>());
break;
+ case TypeTags::RecordId:
case TypeTags::NumberInt64:
val = bitcastFrom<int64_t>(buf.read<int64_t>());
break;
@@ -184,6 +185,7 @@ static void serializeTagValue(BufBuilder& buf, TypeTags tag, Value val) {
case TypeTags::NumberInt32:
buf.appendNum(bitcastTo<int32_t>(val));
break;
+ case TypeTags::RecordId:
case TypeTags::NumberInt64:
buf.appendNum(bitcastTo<int64_t>(val));
break;
@@ -300,6 +302,7 @@ static int getApproximateSize(TypeTags tag, Value val) {
case TypeTags::Timestamp:
case TypeTags::Boolean:
case TypeTags::StringSmall:
+ case TypeTags::RecordId:
break;
// There are deep types.
case TypeTags::NumberDecimal:
diff --git a/src/mongo/db/exec/sbe/values/value.cpp b/src/mongo/db/exec/sbe/values/value.cpp
index a2b1a398753..df65fa01f81 100644
--- a/src/mongo/db/exec/sbe/values/value.cpp
+++ b/src/mongo/db/exec/sbe/values/value.cpp
@@ -161,6 +161,9 @@ void writeTagToStream(T& stream, const TypeTags tag) {
case TypeTags::timeZoneDB:
stream << "timeZoneDB";
break;
+ case TypeTags::RecordId:
+ stream << "RecordId";
+ break;
default:
stream << "unknown tag";
break;
@@ -370,6 +373,9 @@ void writeValueToStream(T& stream, TypeTags tag, Value val) {
stream << "TimeZoneDatabase(" + timeZones.front() + "..." + timeZones.back() + ")";
break;
}
+ case value::TypeTags::RecordId:
+ stream << "RecordId(" << bitcastTo<int64_t>(val) << ")";
+ break;
default:
MONGO_UNREACHABLE;
}
@@ -401,6 +407,7 @@ BSONType tagToType(TypeTags tag) noexcept {
return BSONType::EOO;
case TypeTags::NumberInt32:
return BSONType::NumberInt;
+ case TypeTags::RecordId:
case TypeTags::NumberInt64:
return BSONType::NumberLong;
case TypeTags::NumberDouble:
@@ -449,6 +456,7 @@ std::size_t hashValue(TypeTags tag, Value val) noexcept {
switch (tag) {
case TypeTags::NumberInt32:
return absl::Hash<int32_t>{}(bitcastTo<int32_t>(val));
+ case TypeTags::RecordId:
case TypeTags::NumberInt64:
return absl::Hash<int64_t>{}(bitcastTo<int64_t>(val));
case TypeTags::NumberDouble: {
@@ -695,6 +703,9 @@ std::pair<TypeTags, Value> compareValue(TypeTags lhsTag,
} else if (lhsTag == TypeTags::Nothing && rhsTag == TypeTags::Nothing) {
// Special case for Nothing in a hash table (group) and sort comparison.
return {TypeTags::NumberInt32, bitcastFrom<int32_t>(0)};
+ } else if (lhsTag == TypeTags::RecordId && rhsTag == TypeTags::RecordId) {
+ auto result = compareHelper(bitcastTo<int64_t>(lhsValue), bitcastTo<int64_t>(rhsValue));
+ return {TypeTags::NumberInt32, bitcastFrom<int32_t>(result)};
} else {
// Different types.
auto result =
diff --git a/src/mongo/db/exec/sbe/values/value.h b/src/mongo/db/exec/sbe/values/value.h
index 581da63af19..17c3a970698 100644
--- a/src/mongo/db/exec/sbe/values/value.h
+++ b/src/mongo/db/exec/sbe/values/value.h
@@ -99,6 +99,7 @@ enum class TypeTags : uint8_t {
Object,
ObjectId,
+ RecordId,
// TODO add the rest of mongo types (regex, etc.)
@@ -145,6 +146,10 @@ inline constexpr bool isBinData(TypeTags tag) noexcept {
return tag == TypeTags::bsonBinData;
}
+inline constexpr bool isRecordId(TypeTags tag) noexcept {
+ return tag == TypeTags::RecordId;
+}
+
BSONType tagToType(TypeTags tag) noexcept;
/**
diff --git a/src/mongo/db/exec/sbe/vm/vm.cpp b/src/mongo/db/exec/sbe/vm/vm.cpp
index cf067c690dc..8848c87227e 100644
--- a/src/mongo/db/exec/sbe/vm/vm.cpp
+++ b/src/mongo/db/exec/sbe/vm/vm.cpp
@@ -100,6 +100,7 @@ int Instruction::stackOffset[Instruction::Tags::lastInstruction] = {
0, // isBinData
0, // isDate
0, // isNaN
+ 0, // isRecordId
0, // typeMatch
0, // function is special, the stack offset is encoded in the instruction itself
@@ -326,6 +327,10 @@ void CodeFragment::appendIsNaN() {
appendSimpleInstruction(Instruction::isNaN);
}
+void CodeFragment::appendIsRecordId() {
+ appendSimpleInstruction(Instruction::isRecordId);
+}
+
void CodeFragment::appendTypeMatch(uint32_t typeMask) {
Instruction i;
i.tag = Instruction::typeMatch;
@@ -2602,6 +2607,20 @@ std::tuple<uint8_t, value::TypeTags, value::Value> ByteCode::run(const CodeFragm
}
break;
}
+ case Instruction::isRecordId: {
+ auto [owned, tag, val] = getFromStack(0);
+
+ if (tag != value::TypeTags::Nothing) {
+ topStack(false,
+ value::TypeTags::Boolean,
+ value::bitcastFrom<bool>(value::isRecordId(tag)));
+ }
+
+ if (owned) {
+ value::releaseValue(tag, val);
+ }
+ break;
+ }
case Instruction::typeMatch: {
auto typeMask = value::readFromMemory<uint32_t>(pcPointer);
pcPointer += sizeof(typeMask);
diff --git a/src/mongo/db/exec/sbe/vm/vm.h b/src/mongo/db/exec/sbe/vm/vm.h
index d3d5d360748..124a82217e5 100644
--- a/src/mongo/db/exec/sbe/vm/vm.h
+++ b/src/mongo/db/exec/sbe/vm/vm.h
@@ -151,6 +151,7 @@ struct Instruction {
isBinData,
isDate,
isNaN,
+ isRecordId,
typeMatch,
function,
@@ -297,6 +298,7 @@ public:
void appendIsBinData();
void appendIsDate();
void appendIsNaN();
+ void appendIsRecordId();
void appendTypeMatch(uint32_t typeMask);
void appendFunction(Builtin f, uint8_t arity);
void appendJump(int jumpOffset);
diff --git a/src/mongo/db/query/plan_executor_sbe.cpp b/src/mongo/db/query/plan_executor_sbe.cpp
index 875956d117e..30d2e2dc602 100644
--- a/src/mongo/db/query/plan_executor_sbe.cpp
+++ b/src/mongo/db/query/plan_executor_sbe.cpp
@@ -217,7 +217,7 @@ PlanExecutor::ExecState PlanExecutorSBE::getNext(BSONObj* out, RecordId* dlOut)
uassert(4946306,
"Collection scan was asked to track resume token, but found a result "
"without a valid RecordId",
- tag == sbe::value::TypeTags::NumberInt64 ||
+ tag == sbe::value::TypeTags::RecordId ||
tag == sbe::value::TypeTags::Nothing);
_env->resetSlot(*_resumeRecordIdSlot, tag, val, false);
}
@@ -276,7 +276,7 @@ BSONObj PlanExecutorSBE::getPostBatchResumeToken() const {
str::stream() << "Collection scan was asked to track resume token, "
"but found a result without a valid RecordId: "
<< msgTag,
- tag == sbe::value::TypeTags::NumberInt64);
+ tag == sbe::value::TypeTags::RecordId);
return BSON("$recordId" << sbe::value::bitcastTo<int64_t>(val));
}
}
@@ -313,7 +313,7 @@ sbe::PlanState fetchNext(sbe::PlanStage* root,
if (dlOut) {
invariant(recordIdSlot);
auto [tag, val] = recordIdSlot->getViewOfValue();
- if (tag == sbe::value::TypeTags::NumberInt64) {
+ if (tag == sbe::value::TypeTags::RecordId) {
*dlOut = RecordId{sbe::value::bitcastTo<int64_t>(val)};
}
}
diff --git a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
index 2eef4ba2165..e1fb3257f3d 100644
--- a/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_coll_scan.cpp
@@ -191,7 +191,7 @@ generateOptimizedOplogScan(OperationContext* opCtx,
sbe::makeS<sbe::CoScanStage>(csn->nodeId()), 1, boost::none, csn->nodeId()),
csn->nodeId(),
*seekRecordIdSlot,
- sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::NumberInt64,
+ sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::RecordId,
sbe::value::bitcastFrom<int64_t>(seekRecordId->repr()))),
std::move(stage),
sbe::makeSV(),
@@ -359,7 +359,7 @@ generateGenericCollScan(OperationContext* opCtx,
csn->nodeId(),
seekSlot,
sbe::makeE<sbe::EConstant>(
- sbe::value::TypeTags::NumberInt64,
+ sbe::value::TypeTags::RecordId,
sbe::value::bitcastFrom<int64_t>(csn->resumeAfterRecordId->repr())));
// Construct a 'seek' branch of the 'union'. If we're succeeded to reposition the cursor,
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 64f5543c73f..92dd96f4dc3 100644
--- a/src/mongo/db/query/sbe_stage_builder_index_scan.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_index_scan.cpp
@@ -603,7 +603,7 @@ generateGenericMultiIntervalIndexScan(const CollectionPtr& collection,
makeSlotVector(resultSlot, std::move(indexKeySlots)),
sbe::makeE<sbe::EPrimUnary>(
sbe::EPrimUnary::logicNot,
- sbe::makeE<sbe::EFunction>("isNumber"sv,
+ sbe::makeE<sbe::EFunction>("isRecordId"sv,
sbe::makeEs(sbe::makeE<sbe::EVariable>(resultSlot)))),
ixn->nodeId());
@@ -611,7 +611,7 @@ generateGenericMultiIntervalIndexScan(const CollectionPtr& collection,
return {resultSlot,
sbe::makeS<sbe::FilterStage<false>>(
std::move(spool),
- sbe::makeE<sbe::EFunction>("isNumber"sv,
+ sbe::makeE<sbe::EFunction>("isRecordId"sv,
sbe::makeEs(sbe::makeE<sbe::EVariable>(resultSlot))),
ixn->nodeId())};
}