diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2021-12-10 19:12:48 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-12-10 20:22:20 +0000 |
commit | 54a02037d6032809969031d47711f7657cfdbcee (patch) | |
tree | 2d3a756c5da0a84055c55eab0e22dff97a4896ef | |
parent | 5c95da6983591231793dd12b92fe8fdba2b12894 (diff) | |
download | mongo-54a02037d6032809969031d47711f7657cfdbcee.tar.gz |
SERVER-61993 End interleaved mode when skip if reference object contain empty subobj
(cherry picked from commit 5e924518c279652c7a976ee78e523422ec5ddca7)
-rw-r--r-- | src/mongo/bson/util/bsoncolumn_test.cpp | 31 | ||||
-rw-r--r-- | src/mongo/bson/util/bsoncolumnbuilder.cpp | 12 |
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) { |