summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/sbe/values/slot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/sbe/values/slot.cpp')
-rw-r--r--src/mongo/db/exec/sbe/values/slot.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/src/mongo/db/exec/sbe/values/slot.cpp b/src/mongo/db/exec/sbe/values/slot.cpp
index d827efd1747..607e4dadb59 100644
--- a/src/mongo/db/exec/sbe/values/slot.cpp
+++ b/src/mongo/db/exec/sbe/values/slot.cpp
@@ -31,9 +31,12 @@
#include "mongo/db/exec/sbe/values/slot.h"
+#include "mongo/bson/bsonmisc.h"
#include "mongo/bson/util/builder.h"
#include "mongo/db/exec/js_function.h"
+#include "mongo/db/exec/sbe/values/bson.h"
#include "mongo/db/exec/sbe/values/sort_spec.h"
+#include "mongo/db/exec/sbe/values/value_builder.h"
#include "mongo/db/storage/key_string.h"
#include "mongo/util/bufreader.h"
@@ -363,6 +366,184 @@ static void serializeValue(BufBuilder& buf, TypeTags tag, Value val) {
}
}
+static void serializeValueIntoKeyString(KeyString::Builder& buf, TypeTags tag, Value val) {
+ switch (tag) {
+ case TypeTags::Nothing: {
+ buf.appendBool(false);
+ break;
+ }
+ case TypeTags::NumberInt32: {
+ buf.appendBool(true);
+ buf.appendNumberInt(bitcastTo<int32_t>(val));
+ break;
+ }
+ case TypeTags::NumberInt64: {
+ buf.appendBool(true);
+ buf.appendNumberLong(bitcastTo<int64_t>(val));
+ break;
+ }
+ case TypeTags::NumberDouble: {
+ buf.appendBool(true);
+ buf.appendNumberDouble(bitcastTo<double>(val));
+ break;
+ }
+ case TypeTags::NumberDecimal: {
+ buf.appendBool(true);
+ buf.appendNumberDecimal(value::bitcastTo<Decimal128>(val));
+ break;
+ }
+ case TypeTags::Date: {
+ buf.appendBool(true);
+ buf.appendDate(Date_t::fromMillisSinceEpoch(value::bitcastTo<int64_t>(val)));
+ break;
+ }
+ case TypeTags::Timestamp: {
+ buf.appendBool(true);
+ buf.appendTimestamp(Timestamp(value::bitcastTo<uint64_t>(val)));
+ break;
+ }
+ case TypeTags::Boolean: {
+ buf.appendBool(true);
+ buf.appendBool(bitcastTo<bool>(val));
+ break;
+ }
+ case TypeTags::Null: {
+ buf.appendBool(true);
+ buf.appendNull();
+ break;
+ }
+ case TypeTags::MinKey:
+ case TypeTags::MaxKey: {
+ BSONObjBuilder bob;
+ if (tag == value::TypeTags::MinKey) {
+ bob.appendMinKey("");
+ } else {
+ bob.appendMaxKey("");
+ }
+ buf.appendBool(true);
+ buf.appendBSONElement(bob.obj().firstElement(), nullptr);
+ break;
+ }
+ case TypeTags::bsonUndefined: {
+ buf.appendBool(true);
+ buf.appendUndefined();
+ break;
+ }
+ case TypeTags::StringSmall: {
+ // Small strings cannot contain null bytes, so it is safe to serialize them as plain
+ // C-strings with a null terminator.
+ buf.appendBool(true);
+ buf.appendString(getStringView(tag, val));
+ break;
+ }
+ case TypeTags::StringBig:
+ case TypeTags::bsonString: {
+ buf.appendBool(true);
+ buf.appendString(getStringOrSymbolView(tag, val));
+ break;
+ }
+ case TypeTags::bsonSymbol: {
+ buf.appendBool(true);
+ buf.appendSymbol(getStringOrSymbolView(tag, val));
+ break;
+ }
+ case TypeTags::ArraySet:
+ case TypeTags::Array: {
+ // TODO SERVER-61629: convert this to serialize the 'arr' directly instead of
+ // constructing a BSONArray.
+ BSONArrayBuilder builder;
+ bson::convertToBsonObj(builder, getArrayView(val));
+ buf.appendBool(true);
+ buf.appendArray(BSONArray(builder.done()));
+ break;
+ }
+ case TypeTags::Object: {
+ // TODO SERVER-61629: convert this to serialize the 'obj' directly instead of
+ // constructing a BSONObj.
+ BSONObjBuilder builder;
+ bson::convertToBsonObj(builder, getObjectView(val));
+ buf.appendBool(true);
+ buf.appendObject(builder.done());
+ break;
+ }
+ case TypeTags::ObjectId: {
+ buf.appendBool(true);
+ buf.appendBytes(getObjectIdView(val), sizeof(ObjectIdType));
+ break;
+ }
+ case TypeTags::bsonObject: {
+ buf.appendBool(true);
+ buf.appendObject(BSONObj(getRawPointerView(val)));
+ break;
+ }
+ case TypeTags::bsonArray: {
+ buf.appendBool(true);
+ buf.appendArray(BSONArray(BSONObj(getRawPointerView(val))));
+ break;
+ }
+ case TypeTags::bsonObjectId: {
+ buf.appendBool(true);
+ buf.appendOID(OID::from(getRawPointerView(val)));
+ break;
+ }
+ case TypeTags::bsonBinData: {
+ BufBuilder innerBinDataBuf;
+ innerBinDataBuf.appendUChar(static_cast<uint8_t>(tag));
+ innerBinDataBuf.appendBuf(getRawPointerView(val),
+ getBSONBinDataSize(tag, val) + sizeof(uint32_t) + 1);
+ buf.appendBool(true);
+ buf.appendBinData(
+ BSONBinData(innerBinDataBuf.buf(), innerBinDataBuf.len(), BinDataGeneral));
+ break;
+ }
+ case TypeTags::bsonRegex: {
+ auto regex = getBsonRegexView(val);
+ buf.appendBool(true);
+ buf.appendRegex(BSONRegEx(regex.pattern, regex.flags));
+ break;
+ }
+ case TypeTags::bsonJavascript: {
+ buf.appendBool(true);
+ buf.appendCode(getBsonJavascriptView(val));
+ break;
+ }
+ case TypeTags::bsonDBPointer: {
+ auto dbptr = getBsonDBPointerView(val);
+ buf.appendBool(true);
+ buf.appendDBRef(BSONDBRef(dbptr.ns, OID::from(dbptr.id)));
+ break;
+ }
+ case TypeTags::bsonCodeWScope: {
+ auto cws = getBsonCodeWScopeView(val);
+ buf.appendBool(true);
+ buf.appendCodeWString(BSONCodeWScope(cws.code, BSONObj(cws.scope)));
+ break;
+ }
+ case TypeTags::ksValue: {
+ auto ks = getKeyStringView(val);
+ BufBuilder innerBinDataBuf;
+ innerBinDataBuf.appendUChar(static_cast<uint8_t>(tag));
+ ks->serialize(innerBinDataBuf);
+ buf.appendBool(true);
+ buf.appendBinData(
+ BSONBinData(innerBinDataBuf.buf(), innerBinDataBuf.len(), BinDataGeneral));
+ break;
+ }
+ case TypeTags::RecordId: {
+ // TODO SERVER-61630: Support RecordId strings when sbe also supports this.
+ BufBuilder innerBinDataBuf;
+ innerBinDataBuf.appendUChar(static_cast<uint8_t>(tag));
+ innerBinDataBuf.appendNum(bitcastTo<int64_t>(val));
+ buf.appendBool(true);
+ buf.appendBinData(BSONBinData(
+ innerBinDataBuf.buf(), innerBinDataBuf.len(), BinDataType::BinDataGeneral));
+ break;
+ }
+ default:
+ MONGO_UNREACHABLE;
+ }
+}
+
void MaterializedRow::serializeForSorter(BufBuilder& buf) const {
buf.appendNum(size());
@@ -372,6 +553,32 @@ void MaterializedRow::serializeForSorter(BufBuilder& buf) const {
}
}
+void MaterializedRow::serializeIntoKeyString(KeyString::Builder& buf) const {
+ for (size_t idx = 0; idx < size(); ++idx) {
+ auto [tag, val] = getViewOfValue(idx);
+ serializeValueIntoKeyString(buf, tag, val);
+ }
+}
+
+MaterializedRow MaterializedRow::deserializeFromKeyString(const KeyString::Value& keyString,
+ BufBuilder* valueBufferBuilder) {
+ BufReader reader(keyString.getBuffer(), keyString.getSize());
+ KeyString::TypeBits typeBits(keyString.getTypeBits());
+ KeyString::TypeBits::Reader typeBitsReader(typeBits);
+
+ MaterializedRowValueBuilder valBuilder(valueBufferBuilder);
+ auto keepReading = true;
+ do {
+ keepReading = KeyString::readSBEValue(
+ &reader, &typeBitsReader, false /* inverted */, typeBits.version, &valBuilder);
+ } while (keepReading);
+
+ MaterializedRow result{valBuilder.numValues()};
+ valBuilder.readValues(result);
+
+ return result;
+}
+
int getApproximateSize(TypeTags tag, Value val) {
int result = sizeof(tag) + sizeof(val);
switch (tag) {