summaryrefslogtreecommitdiff
path: root/src/mongo/bson
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2021-12-10 19:12:48 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-10 19:38:27 +0000
commit5e924518c279652c7a976ee78e523422ec5ddca7 (patch)
treef0f60f2579646c56eb8a5ebef1a32e0f4ce0f764 /src/mongo/bson
parent4e84caad15015f8ccbb1a825cfed7d3b55cc5524 (diff)
downloadmongo-5e924518c279652c7a976ee78e523422ec5ddca7.tar.gz
SERVER-61993 End interleaved mode when skip if reference object contain empty subobj
Diffstat (limited to 'src/mongo/bson')
-rw-r--r--src/mongo/bson/util/bsoncolumn_test.cpp31
-rw-r--r--src/mongo/bson/util/bsoncolumnbuilder.cpp12
2 files changed, 42 insertions, 1 deletions
diff --git a/src/mongo/bson/util/bsoncolumn_test.cpp b/src/mongo/bson/util/bsoncolumn_test.cpp
index 6ab45991fb2..17572486ea0 100644
--- a/src/mongo/bson/util/bsoncolumn_test.cpp
+++ b/src/mongo/bson/util/bsoncolumn_test.cpp
@@ -3577,6 +3577,37 @@ TEST_F(BSONColumnTest, InterleavedIncompatibleAfterDeterminedReference) {
verifyDecompression(binData, elems);
}
+TEST_F(BSONColumnTest, InterleavedSkipAfterEmptySubObj) {
+ BSONColumnBuilder cb("test"_sd);
+
+ std::vector<BSONElement> elems = {
+ createElementObj(BSON("x" << 1 << "y" << 2 << "z" << BSON("z1" << BSONObjBuilder().obj()))),
+ BSONElement()};
+
+ for (auto elem : elems) {
+ if (!elem.eoo())
+ cb.append(elem);
+ else
+ cb.skip();
+ }
+
+ BufBuilder expected;
+ appendInterleavedStart(expected, elems.front().Obj());
+ appendSimple8bControl(expected, 0b1000, 0b0000);
+ appendSimple8bBlocks64(expected, {kDeltaForBinaryEqualValues}, 1);
+ appendSimple8bControl(expected, 0b1000, 0b0000);
+ appendSimple8bBlocks64(expected, {kDeltaForBinaryEqualValues}, 1);
+ appendEOO(expected);
+
+ appendSimple8bControl(expected, 0b1000, 0b0000);
+ appendSimple8bBlock64(expected, boost::none);
+ appendEOO(expected);
+
+ auto binData = cb.finalize();
+ verifyBinary(binData, expected);
+ verifyDecompression(binData, elems);
+}
+
TEST_F(BSONColumnTest, ObjectEmpty) {
BSONColumnBuilder cb("test"_sd);
diff --git a/src/mongo/bson/util/bsoncolumnbuilder.cpp b/src/mongo/bson/util/bsoncolumnbuilder.cpp
index 3a77fdbd83c..9156b56a5f4 100644
--- a/src/mongo/bson/util/bsoncolumnbuilder.cpp
+++ b/src/mongo/bson/util/bsoncolumnbuilder.cpp
@@ -360,7 +360,17 @@ BSONColumnBuilder& BSONColumnBuilder::append(BSONElement elem) {
BSONColumnBuilder& BSONColumnBuilder::skip() {
if (_mode == Mode::kRegular) {
_state.skip();
- } else if (_mode == Mode::kSubObjDeterminingReference) {
+ return *this;
+ }
+
+ // If the reference object contain any empty subobjects we need to end interleaved mode as
+ // skipping in all substreams would not be encoded as skipped root object.
+ if (_hasEmptyObj(_referenceSubObj)) {
+ _flushSubObjMode();
+ return skip();
+ }
+
+ if (_mode == Mode::kSubObjDeterminingReference) {
_bufferedObjElements.push_back(BSONObj());
} else {
for (auto&& state : _subobjStates) {